Can you find all classes in a package using reflection?

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

    Here's how I do it. I scan all the subfolders (sub-packages) and I don't try to load anonymous classes:

       /**
       * Attempts to list all the classes in the specified package as determined
       * by the context class loader, recursively, avoiding anonymous classes
       * 
       * @param pckgname
       *            the package name to search
       * @return a list of classes that exist within that package
       * @throws ClassNotFoundException
       *             if something went wrong
       */
      private static List getClassesForPackage(String pckgname) throws ClassNotFoundException {
          // This will hold a list of directories matching the pckgname. There may be more than one if a package is split over multiple jars/paths
          ArrayList directories = new ArrayList();
          String packageToPath = pckgname.replace('.', '/');
          try {
              ClassLoader cld = Thread.currentThread().getContextClassLoader();
              if (cld == null) {
                  throw new ClassNotFoundException("Can't get class loader.");
              }
    
              // Ask for all resources for the packageToPath
              Enumeration resources = cld.getResources(packageToPath);
              while (resources.hasMoreElements()) {
                  directories.add(new File(URLDecoder.decode(resources.nextElement().getPath(), "UTF-8")));
              }
          } catch (NullPointerException x) {
              throw new ClassNotFoundException(pckgname + " does not appear to be a valid package (Null pointer exception)");
          } catch (UnsupportedEncodingException encex) {
              throw new ClassNotFoundException(pckgname + " does not appear to be a valid package (Unsupported encoding)");
          } catch (IOException ioex) {
              throw new ClassNotFoundException("IOException was thrown when trying to get all resources for " + pckgname);
          }
    
          ArrayList classes = new ArrayList();
          // For every directoryFile identified capture all the .class files
          while (!directories.isEmpty()){
              File directoryFile  = directories.remove(0);             
              if (directoryFile.exists()) {
                  // Get the list of the files contained in the package
                  File[] files = directoryFile.listFiles();
    
                  for (File file : files) {
                      // we are only interested in .class files
                      if ((file.getName().endsWith(".class")) && (!file.getName().contains("$"))) {
                          // removes the .class extension
                          int index = directoryFile.getPath().indexOf(packageToPath);
                          String packagePrefix = directoryFile.getPath().substring(index).replace('/', '.');;                          
                        try {                  
                          String className = packagePrefix + '.' + file.getName().substring(0, file.getName().length() - 6);                            
                          classes.add(Class.forName(className));                                
                        } catch (NoClassDefFoundError e)
                        {
                          // do nothing. this class hasn't been found by the loader, and we don't care.
                        }
                      } else if (file.isDirectory()){ // If we got to a subdirectory
                          directories.add(new File(file.getPath()));                          
                      }
                  }
              } else {
                  throw new ClassNotFoundException(pckgname + " (" + directoryFile.getPath() + ") does not appear to be a valid package");
              }
          }
          return classes;
      }  
    

提交回复
热议问题