java 获取某个包下的所有类名

本方法支持class 模式和jar 包模式

package com.yoke.util;

import com.yoke.md5util.UrlDecode;
import com.yoke.util.file.FileUtil;

import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

/**
 * @author jiangzeyin
 * @date 2016-9-9
 */
public class PackageUtil {

    /**
     * 获取某包下(包括该包的所有子包)所有类
     *
     * @param packageName 包名
     * @return 类的完整名称
     * @throws UnsupportedEncodingException
     */
    public static List<String> getClassName(String packageName) throws IOException {
        return getClassName(packageName, true);
    }

    /**
     * 获取某包下所有类
     *
     * @param packageName  包名
     * @param childPackage 是否遍历子包
     * @return 类的完整名称
     * @throws UnsupportedEncodingException
     */
    public static List<String> getClassName(String packageName, boolean childPackage) throws IOException {
        List<String> fileNames = new ArrayList<>();
        ClassLoader loader = Thread.currentThread().getContextClassLoader();
        String packagePath = packageName.replace(".", "/");
        Enumeration<URL> urls = loader.getResources(packagePath);
        while (urls.hasMoreElements()) {
            URL url = urls.nextElement();
            if (url == null)
                continue;
            String type = url.getProtocol();
            if (type.equals("file")) {
                fileNames.addAll(getClassNameByFile(url.getPath(), childPackage));
            } else if (type.equals("jar")) {
                fileNames.addAll(getClassNameByJar(url.getPath(), childPackage));
            }
        }
        fileNames.addAll(getClassNameByJars(((URLClassLoader) loader).getURLs(), packagePath, childPackage));
        return fileNames;
    }

    /**
     * 从项目文件获取某包下所有类
     *
     * @param filePath     文件路径
     *                     类名集合
     * @param childPackage 是否遍历子包
     * @return 类的完整名称
     * @throws UnsupportedEncodingException
     */
    private static List<String> getClassNameByFile(String filePath, boolean childPackage) throws UnsupportedEncodingException {
        List<String> myClassName = new ArrayList<>();
        filePath = UrlDecode.getURLDecode(filePath);
        File file = new File(filePath);
        File[] childFiles = file.listFiles();
        if (childFiles == null)
            return myClassName;
        for (File childFile : childFiles) {
            if (childFile.isDirectory()) {
                if (childPackage) {
                    myClassName.addAll(getClassNameByFile(childFile.getPath(), childPackage));
                }
            } else {
                String childFilePath = childFile.getPath();
                childFilePath = FileUtil.clearPath(childFilePath);
                if (childFilePath.endsWith(".class")) {
                    childFilePath = childFilePath.substring(childFilePath.indexOf("/classes/") + 9, childFilePath.lastIndexOf("."));
                    childFilePath = childFilePath.replace("/", ".");
                    myClassName.add(childFilePath);
                }
            }
        }
        return myClassName;
    }

    /**
     * 从jar获取某包下所有类
     *
     * @param jarPath      jar文件路径
     * @param childPackage 是否遍历子包
     * @return 类的完整名称
     * @throws UnsupportedEncodingException
     */
    private static List<String> getClassNameByJar(String jarPath, boolean childPackage) throws UnsupportedEncodingException {
        List<String> myClassName = new ArrayList<String>();
        String[] jarInfo = jarPath.split("!");
        String jarFilePath = jarInfo[0].substring(jarInfo[0].indexOf("/"));
        jarFilePath = UrlDecode.getURLDecode(jarFilePath);
        String packagePath = jarInfo[1].substring(1);
        try {
            JarFile jarFile = new JarFile(jarFilePath);
            Enumeration<JarEntry> entrys = jarFile.entries();
            while (entrys.hasMoreElements()) {
                JarEntry jarEntry = entrys.nextElement();
                String entryName = jarEntry.getName();
                if (entryName.endsWith(".class")) {
                    if (childPackage) {
                        if (entryName.startsWith(packagePath)) {
                            entryName = entryName.replace("/", ".").substring(0, entryName.lastIndexOf("."));
                            myClassName.add(entryName);
                        }
                    } else {
                        int index = entryName.lastIndexOf("/");
                        String myPackagePath;
                        if (index != -1) {
                            myPackagePath = entryName.substring(0, index);
                        } else {
                            myPackagePath = entryName;
                        }
                        if (myPackagePath.equals(packagePath)) {
                            entryName = entryName.replace("/", ".").substring(0, entryName.lastIndexOf("."));
                            myClassName.add(entryName);
                        }
                    }
                }
            }
        } catch (Exception e) {
            //SystemLog.Log(LogType.systemInfo, e.getMessage(), e);
        }
        return myClassName;
    }

    /**
     * 从所有jar中搜索该包,并获取该包下所有类
     *
     * @param urls         URL集合
     * @param packagePath  包路径
     * @param childPackage 是否遍历子包
     * @return 类的完整名称
     * @throws UnsupportedEncodingException
     */
    private static List<String> getClassNameByJars(URL[] urls, String packagePath, boolean childPackage) throws UnsupportedEncodingException {
        List<String> myClassName = new ArrayList<String>();
        if (urls != null) {
            for (int i = 0; i < urls.length; i++) {
                URL url = urls[i];
                String urlPath = url.getPath();
                // 不必搜索classes文件夹
                if (urlPath.endsWith("classes/")) {
                    continue;
                }
                String jarPath = urlPath + "!/" + packagePath;
                myClassName.addAll(getClassNameByJar(jarPath, childPackage));
            }
        }
        return myClassName;
    }
}

本方法是本人在网上看到,拿来用后面发现如果class 所在路径中存在中文则不行,本方法修护了这个问题。

关键代码是在 108行 对其路径进行url 编码

时间: 2024-11-01 08:58:44

java 获取某个包下的所有类名的相关文章

java 获取指定目录下的所有文件

Java ,如何获取指定目录下的所有文件呢? 看代码: Java代码   /***       * 获取指定目录下的所有的文件(不包括文件夹),采用了递归       *        * @param obj       * @return       */       public static ArrayList<File> getListFiles(Object obj) {           File directory = null;           if (obj inst

Predicate和Consumer接口– Java 8中java.util.function包下的接口

早先我写了一篇<函数式接口>,探讨了部分Java 8中函数式接口的用法.我也提及了Predicate接口属于java.util.function包,在这篇文章中,我将展示如何应用Predicate接口和Consumer接口. 一起看一下Predicate的官方文档: Determines if the input object matches some criteria. 即判断输入的对象是否符合某个条件. 在Predicate接口中,有以下5个方法(你肯定好奇为何此接口属于函数式接口.如果你

java 获取同一个网关下不同客户端的ip

问题描述 外网tomcat服务器 公司内网访问服务器时,服务器上request.getRemoteAddr只获取到公司的网关的ip,我要得到公司内网中不同客户端的不同ip,我该怎么办?我没分!见谅! 解决方案 用js在你的页面上获取客户端本地ip,然后传送给你的服务器直接在request里获取不到解决方案二:引用外网tomcat服务器 公司内网访问服务器时,服务器上request.getRemoteAddr只获取到公司的网关的ip,我要得到公司内网中不同客户端的不同ip,我该怎么办? 局域网 访

Function接口 – Java8中java.util.function包下的函数式接口

早先我写了一篇<函数式接口>,探讨了Java8中函数式接口的用法.如果你正在浏览Java8的API,你会发现java.util.function中 Function, Supplier, Consumer, Predicate和其他函数式接口广泛用在支持lambda表达式的API中.这些接口有一个抽象方法,会被lambda表达式的定义所覆盖.在这篇文章中,我会简单描述Function接口,该接口目前已发布在java.util.function中. Function接口的主要方法: R appl

java.lang包下的类能不能被代理,为什么??

问题描述 java.lang包下的类能不能被代理,为什么?? 今天碰到一个问题,说是java.lang下的类不能被代理? 想知道原因是什么? 解决方案 绝对不能.要是你能随便代理,那JVM的安全何在? java.lang这个包是java的核心包.这个包下的类是有顶级的BootStrap 引导类加载器加载.java的类加载器是双亲委派机制,意思就是上层加载器加载过了,就不再加载. 举个例子,你自己定义一个类加载器.自己写个java.lang.String类,然后尝试着用自己的类加载器去加载,绝对加

深入探讨 java.lang.ref 包

简介: 本文主要探讨了 java.lang.ref 包的使用方法,以及源码解读.并就该包在不同 JVM 上的表现进行了比较与分析.通过阅读本文,读者可以加深对 java.lang.ref 的理解,从而在开发中更好地利用该包. 概述 Java.lang.ref 是 Java 类库中比较特殊的一个包,它提供了与 Java 垃圾回收器密切相关的引用类.这些引用类对象可以指向其它对象,但它们不同于一般的引用,因为它们的存在并不防碍 Java 垃圾回收器对它们所指向的对象进行回收.其好处就在于使者可以保持

class-java同一个包下,类名改变一个数字结果完全不同,遇到鬼了

问题描述 java同一个包下,类名改变一个数字结果完全不同,遇到鬼了 src上的Six2和Six3当时位置是同条件的. 解决方案 问题是,你的Six2是与其他类定义在一个文件中的,不是独立的类,它的main方法就不能作为程序的入口了. 而且这还是有编译错误的,我这里按你这段代码将Six2定义为public ,是无法编译通过的,必须去掉public才行,但是去掉public后,main方法就无法运行了. 结论就是:java语法规定,具有main方法的类必须是具有单独文件的类,将Six2挪出来就正确

给定一个jar包,怎样得到他里面指定包下的所有类的类名。

问题描述 给定一个jar包,怎样得到他里面指定包下的所有类的类名. 解决方案 方法一:java.util.jar.JarFileJarFile jar = new JarFile("path");Enumeration enumeration = jar.entries();while(enumeration.hasMoreElements()){System.out.println(enumeration.nextElement());}你这样输出一下,看结果就知道里面的内容是什么了

LinuxC下获取UDP包中的路由目的IP地址和头标识目的地址

在接受到UDP包后,有时候我们需要根据所接收到得UDP包,获取它的路由目的IP地址和头标识目的地址. (一)主要的步骤: 在setsockopt中设置IP_PKTINFO,然后通过recvmsg来获取struct in_pktinfo(struct in_pktinfo是struct msghdr中msg_control的成员).in_pktinfo 结构体(如下所示),我们可以从in_pktinfo中获取路由目的地址(destination address of the packet).头标识