Can you find all classes in a package using reflection?

前端 未结 27 2215
不知归路
不知归路 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:56

    I've been trying to use the Reflections library, but had some problems using it, and there were too many jars I should include just to simply obtain the classes on a package.

    I'll post a solution I've found in this duplicate question: How to get all classes names in a package?

    The answer was written by sp00m; I've added some corrections to make it work:

    import java.io.File;
    import java.io.IOException;
    import java.net.URL;
    import java.util.Enumeration;
    import java.util.LinkedList;
    import java.util.List;
    
    public final class ClassFinder {
    
        private final static char DOT = '.';
        private final static char SLASH = '/';
        private final static String CLASS_SUFFIX = ".class";
        private final static String BAD_PACKAGE_ERROR = "Unable to get resources from path '%s'. Are you sure the given '%s' package exists?";
    
        public final static List> find(final String scannedPackage) {
            final ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
            final String scannedPath = scannedPackage.replace(DOT, SLASH);
            final Enumeration resources;
            try {
                resources = classLoader.getResources(scannedPath);
            } catch (IOException e) {
                throw new IllegalArgumentException(String.format(BAD_PACKAGE_ERROR, scannedPath, scannedPackage), e);
            }
            final List> classes = new LinkedList>();
            while (resources.hasMoreElements()) {
                final File file = new File(resources.nextElement().getFile());
                classes.addAll(find(file, scannedPackage));
            }
            return classes;
        }
    
        private final static List> find(final File file, final String scannedPackage) {
            final List> classes = new LinkedList>();
            if (file.isDirectory()) {
                for (File nestedFile : file.listFiles()) {
                    classes.addAll(find(nestedFile, scannedPackage));
                }
            //File names with the $1, $2 holds the anonymous inner classes, we are not interested on them. 
            } else if (file.getName().endsWith(CLASS_SUFFIX) && !file.getName().contains("$")) {
    
                final int beginIndex = 0;
                final int endIndex = file.getName().length() - CLASS_SUFFIX.length();
                final String className = file.getName().substring(beginIndex, endIndex);
                try {
                    final String resource = scannedPackage + DOT + className;
                    classes.add(Class.forName(resource));
                } catch (ClassNotFoundException ignore) {
                }
            }
            return classes;
        }
    
    }
    

    To use it just call the find method as sp00n mentioned in this example: I've added the creation of instances of the classes if needed.

    List> classes = ClassFinder.find("com.package");
    
    ExcelReporting excelReporting;
    for (Class aClass : classes) {
        Constructor constructor = aClass.getConstructor();
        //Create an object of the class type
        constructor.newInstance();
        //...
    }
    

提交回复
热议问题