Can you find all classes in a package using reflection?

前端 未结 27 2229
不知归路
不知归路 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 06:00

    Almost all the answers either uses Reflections or reads class files from file system. If you try to read classes from file system, you may get errors when you package your application as JAR or other. Also you may not want to use a separate library for that purpose.

    Here is another approach which is pure java and not depends on file system.

    import javax.tools.JavaFileObject;
    import javax.tools.StandardJavaFileManager;
    import javax.tools.StandardLocation;
    import javax.tools.ToolProvider;
    import java.io.File;
    import java.util.ArrayList;
    import java.util.Collection;
    import java.util.Collections;
    import java.util.regex.Pattern;
    import java.util.stream.Collectors;
    import java.util.stream.StreamSupport;
    
    public class PackageUtil {
    
        public static Collection getClasses(final String pack) throws Exception {
            final StandardJavaFileManager fileManager = ToolProvider.getSystemJavaCompiler().getStandardFileManager(null, null, null);
            return StreamSupport.stream(fileManager.list(StandardLocation.CLASS_PATH, pack, Collections.singleton(JavaFileObject.Kind.CLASS), false).spliterator(), false)
                    .map(javaFileObject -> {
                        try {
                            final String[] split = javaFileObject.getName()
                                    .replace(".class", "")
                                    .replace(")", "")
                                    .split(Pattern.quote(File.separator));
    
                            final String fullClassName = pack + "." + split[split.length - 1];
                            return Class.forName(fullClassName);
                        } catch (ClassNotFoundException e) {
                            throw new RuntimeException(e);
                        }
    
                    })
                    .collect(Collectors.toCollection(ArrayList::new));
        }
    }
    

    Java 8 is not a must. You can use for loops instead of streams. And you can test it like this

    public static void main(String[] args) throws Exception {
        final String pack = "java.nio.file"; // Or any other package
        PackageUtil.getClasses(pack).stream().forEach(System.out::println);
    }
    

提交回复
热议问题