2012-06-06 2 views
8

Мне нужен класс [] всех файлов классов, содержащихся в одном из моих исходных пакетов на Java.Получите массив файлов классов внутри пакета в Java

Я не мог найти стандартный способ сделать это одним выстрелом. Если кто-то может написать функцию для извлечения этого списка, это будет действительно полезно.

Class[] myClasses = yourfunction(); // Return a list of class inside a source package in the currently working project in java 
+0

Нет стандартного способа перечисления всех классов в данном пакете. В некоторых случаях это даже не возможно (подумайте о загрузке классов URLClassLoader из URL-адреса HTTP: нет стандартного способа перечисления файлов в папке). –

+1

См. Здесь справочное обходное решение (это не доказательство дурака) - http://stackoverflow.com/questions/176527/how-can-i-enumerate-all-classes-in-a-package-and-add-them- to-a-list – Perception

ответ

7

Я могу решить эту проблему, используя обычный файл ввода-вывода и механизм поиска. Вы можете проверить ответ, как указано здесь.

private static List<Class> getClassesForPackage(Package pkg) { 
    String pkgname = pkg.getName(); 

    List<Class> classes = new ArrayList<Class>(); 

    // Get a File object for the package 
    File directory = null; 
    String fullPath; 
    String relPath = pkgname.replace('.', '/'); 

    //System.out.println("ClassDiscovery: Package: " + pkgname + " becomes Path:" + relPath); 

    URL resource = ClassLoader.getSystemClassLoader().getResource(relPath); 

    //System.out.println("ClassDiscovery: Resource = " + resource); 
    if (resource == null) { 
     throw new RuntimeException("No resource for " + relPath); 
    } 
    fullPath = resource.getFile(); 
    //System.out.println("ClassDiscovery: FullPath = " + resource); 

    try { 
     directory = new File(resource.toURI()); 
    } catch (URISyntaxException e) { 
     throw new RuntimeException(pkgname + " (" + resource + ") does not appear to be a valid URL/URI. Strange, since we got it from the system...", e); 
    } catch (IllegalArgumentException e) { 
     directory = null; 
    } 
    //System.out.println("ClassDiscovery: Directory = " + directory); 

    if (directory != null && directory.exists()) { 

     // Get the list of the files contained in the package 
     String[] files = directory.list(); 
     for (int i = 0; i < files.length; i++) { 

      // we are only interested in .class files 
      if (files[i].endsWith(".class")) { 

       // removes the .class extension 
       String className = pkgname + '.' + files[i].substring(0, files[i].length() - 6); 

       //System.out.println("ClassDiscovery: className = " + className); 

       try { 
        classes.add(Class.forName(className)); 
       } catch (ClassNotFoundException e) { 
        throw new RuntimeException("ClassNotFoundException loading " + className); 
       } 
      } 
     } 
    } else { 
     try { 
      String jarPath = fullPath.replaceFirst("[.]jar[!].*", ".jar").replaceFirst("file:", ""); 
      JarFile jarFile = new JarFile(jarPath); 
      Enumeration<JarEntry> entries = jarFile.entries(); 
      while (entries.hasMoreElements()) { 
       JarEntry entry = entries.nextElement(); 
       String entryName = entry.getName(); 
       if (entryName.startsWith(relPath) && entryName.length() > (relPath.length() + "/".length())) { 

        //System.out.println("ClassDiscovery: JarEntry: " + entryName); 
        String className = entryName.replace('/', '.').replace('\\', '.').replace(".class", ""); 

        //System.out.println("ClassDiscovery: className = " + className); 
        try { 
         classes.add(Class.forName(className)); 
        } catch (ClassNotFoundException e) { 
         throw new RuntimeException("ClassNotFoundException loading " + className); 
        } 
       } 
      } 
     } catch (IOException e) { 
      throw new RuntimeException(pkgname + " (" + directory + ") does not appear to be a valid package", e); 
     } 
    } 
    return classes; 
} 
+4

Soooo большой, должен быть более простой способ ... – Illidanek

+0

@Illidanek ya вы можете определенно сократить некоторые строки кода из этого кода, а также лучшее решение может существовать, даже если бы я хотел бы видеть более короткие и более эффективный код, выполняющий ту же работу. – AurA

+0

Хороший ответ ... сэкономил время моей партии –

3

Не пробовал это на всех виртуальных машин, но на недавнем Oracle VM есть более короткий путь:

Enumeration<URL> resources = Thread.currentThread().getContextClassLoader().getResources("package/name/with/slashes/instead/dots"); 
    while (resources.hasMoreElements()) { 
     URL url = resources.nextElement(); 
     System.out.println(url); 
     System.out.println(new Scanner((InputStream) url.getContent()).useDelimiter("\\A").next()); 
    } 

Это напечатает имена ресурсов в пакете, так что вы можете используйте getResource(...) на них. Вызов url.getContent() вернет экземпляр sun.net.www.content.text.PlainTextInputStream, который является классом VM.

+2

Это не работает с jar под jdk 1.8. 'sun.net.www.protocol.jar.JarURLConnection $ JarURLInputStream' бросает NPE на попытку прочитать из него. – Vadzim

Смежные вопросы