你可以使用反射找到一个包里面所有的类吗?| Java Debug 笔记

本文正在参加「Java主题月 – Java Debug笔记活动」,详情查看 活动链接

你可以使用反射找到一个包里面所有的类吗?

有可能找到给定包里面所有的类吗?(例如快速查看一个包,但是这好像是不存在)

回答一

谷歌的GUava 14 包含了一个有3种方法的新类ClassPath去扫描顶级类

getTopLevelClasses()
getTopLevelClasses(String packageName)
getTopLevelClassesRecursive(String packageName)
复制代码

想知道更多那就去看Java的ClassPath 文档

回答二

不用任何的外部库

package test;

import java.io.DataInputStream;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

public class Test {
    public static void main(String[] args) throws Exception{
        List<Class> classes = getClasses(Test.class.getClassLoader(),"test");
        for(Class c:classes){
            System.out.println("Class: "+c);
        }
    }

    public static List<Class> getClasses(ClassLoader cl,String pack) throws Exception{

        String dottedPackage = pack.replaceAll("[/]", ".");
        List<Class> classes = new ArrayList<Class>();
        URL upackage = cl.getResource(pack);

        DataInputStream dis = new DataInputStream((InputStream) upackage.getContent());
        String line = null;
        while ((line = dis.readLine()) != null) {
            if(line.endsWith(".class")) {
               classes.add(Class.forName(dottedPackage+"."+line.substring(0,line.lastIndexOf('.'))));
            }
        }
        return classes;
    }
}
复制代码

回答三

下面这个怎么样

public static List<Class<?>> getClassesForPackage(final String pkgName) throws IOException, URISyntaxException {
    final String pkgPath = pkgName.replace('.', '/');
    final URI pkg = Objects.requireNonNull(ClassLoader.getSystemClassLoader().getResource(pkgPath)).toURI();
    final ArrayList<Class<?>> allClasses = new ArrayList<Class<?>>();

    Path root;
    if (pkg.toString().startsWith("jar:")) {
        try {
            root = FileSystems.getFileSystem(pkg).getPath(pkgPath);
        } catch (final FileSystemNotFoundException e) {
            root = FileSystems.newFileSystem(pkg, Collections.emptyMap()).getPath(pkgPath);
        }
    } else {
        root = Paths.get(pkg);
    }

    final String extension = ".class";
    try (final Stream<Path> allPaths = Files.walk(root)) {
        allPaths.filter(Files::isRegularFile).forEach(file -> {
            try {
                final String path = file.toString().replace('/', '.');
                final String name = path.substring(path.indexOf(pkgName), path.length() - extension.length());
                allClasses.add(Class.forName(name));
            } catch (final ClassNotFoundException | StringIndexOutOfBoundsException ignored) {
            }
        });
    }
    return allClasses;
}
复制代码

然后你可以重载这个方法

public static List<Class<?>> getClassesForPackage(final Package pkg) throws IOException, URISyntaxException {
    return getClassesForPackage(pkg.getName());
}
If you need to test it:

public static void main(final String[] argv) throws IOException, URISyntaxException {
    for (final Class<?> cls : getClassesForPackage("my.package")) {
        System.out.println(cls);
    }
    for (final Class<?> cls : getClassesForPackage(MyClass.class.getPackage())) {
        System.out.println(cls);
    }
}
复制代码

如果你的IDE没有导入助手的话

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.file.FileSystemNotFoundException;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.stream.Stream;
复制代码

代码运行在你的IDE里面,可以打包成jar,不需要任何外部依赖

文章翻译自Stack Overflow:stackoverflow.com/questions/5…

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享