Can you find all classes in a package using reflection?

前端 未结 27 3046
不知归路
不知归路 2020-11-21 05:24

Is it possible to find all classes or interfaces in a given package? (Quickly looking at e.g. Package, it would seem like no.)

27条回答
  •  夕颜
    夕颜 (楼主)
    2020-11-21 05:51

    What about this:

    public static List> getClassesForPackage(final String pkgName) throws IOException, URISyntaxException {
        final String pkgPath = pkgName.replace('.', '/');
        final URI pkg = Objects.requireNonNull(ClassLoader.getSystemClassLoader().getResource(pkgPath)).toURI();
        final ArrayList> allClasses = new ArrayList>();
    
        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 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;
    }
    

    You can then overload the function:

    public static List> 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);
        }
    }
    

    If your IDE does not have import helper:

    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;
    

    It works:

    • from your IDE

    • for a JAR file

    • without external dependencies

提交回复
热议问题