2009-07-20 20 views

Odpowiedz

10

Nie możesz. Zajęcia mogą odbywać się za pośrednictwem wielu różnych programów ładujących klasy, w tym zdalnych.

1

Nie ma globalnego sposobu, aby to zrobić. Biorąc to pod uwagę, jeśli wiesz, skąd pochodzą twoje klasy, możesz przejść do katalogu pliku jar lub systemu plików.

3

Jest to fragment z here że robi dokładnie to, co chcesz, zakładając klas można znaleźć lokalnie:

private static Class[] getClasses(String packageName) 
throws ClassNotFoundException, IOException { 
    ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); 
    assert classLoader != null; 
    String path = packageName.replace('.', '/'); 
    Enumeration<URL> resources = classLoader.getResources(path); 
    List<File> dirs = new ArrayList<File>(); 
    while (resources.hasMoreElements()) { 
     URL resource = resources.nextElement(); 
     dirs.add(new File(resource.getFile())); 
    } 
    ArrayList<Class> classes = new ArrayList<Class>(); 
    for (File directory : dirs) { 
     classes.addAll(findClasses(directory, packageName)); 
    } 
    return classes.toArray(new Class[classes.size()]); 
} 

private static List<Class> findClasses(File directory, String packageName) throws ClassNotFoundException { 
    List<Class> classes = new ArrayList<Class>(); 
    if (!directory.exists()) { 
     return classes; 
    } 
    File[] files = directory.listFiles(); 
    for (File file : files) { 
     if (file.isDirectory()) { 
      assert !file.getName().contains("."); 
      classes.addAll(findClasses(file, packageName + "." + file.getName())); 
     } else if (file.getName().endsWith(".class")) { 
      classes.add(Class.forName(packageName + '.' + file.getName().substring(0, file.getName().length() - 6))); 
     } 
    } 
    return classes; 
} 
+0

Czy to działa z klasami słoików? –

+0

O ile mogę powiedzieć, to się nie powiedzie, jeśli masz słoik (-1), ale jest przyzwoitym rutyną szukania plików .class dla odkrycia (+1), więc możesz się zepsuć :) –

+0

Powyższy kod nie tylko zakłada, że klasy z danego pakietu są lokalne, ale także, że wszystkie zostały załadowane przez ten sam program ładujący klasy I nie zostały spakowane. – ChssPly76

1

Java nie mają odkrycia.

Większość produktów, które mają możliwość dodawania (odkrywania) nowych klas, może mieć plik tekstowy opisujący "Rozszerzenia programów" lub określony katalog, w którym można umieścić klasy lub słoiki z wykorzystaniem sztuczki, takiej jak opisany @JG. (To właśnie robi eclipse i jest zalecane dla każdego rozwiązania, w którym użytkownik może ręcznie dodać nowy moduł).

+1

Nie zapomnij o API SPI dla wtyczek. Zapewniają one rozsądnie eleganckie rozwiązanie dla frameworków wtyczek. – jsight

7

Oto dokładniejszy sposób rozwiązania tego problemu dla słoików, w oparciu o pomysł opublikowany przez JG.

/** 
* Scans all classloaders for the current thread for loaded jars, and then scans 
* each jar for the package name in question, listing all classes directly under 
* the package name in question. Assumes directory structure in jar file and class 
* package naming follow java conventions (i.e. com.example.test.MyTest would be in 
* /com/example/test/MyTest.class) 
*/ 
public Collection<Class> getClassesForPackage(String packageName) throws Exception { 
    String packagePath = packageName.replace(".", "/"); 
    ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); 
    Set<URL> jarUrls = new HashSet<URL>(); 

    while (classLoader != null) { 
    if (classLoader instanceof URLClassLoader) 
     for (URL url : ((URLClassLoader) classLoader).getURLs()) 
     if (url.getFile().endsWith(".jar") // may want better way to detect jar files 
      jarUrls.add(url); 

    classLoader = classLoader.getParent(); 
    } 

    Set<Class> classes = new HashSet<Class>(); 

    for (URL url : jarUrls) { 
    JarInputStream stream = new JarInputStream(url.openStream()); // may want better way to open url connections 
    JarEntry entry = stream.getNextJarEntry(); 

    while (entry != null) { 
     String name = entry.getName(); 
     int i = name.lastIndexOf("/"); 

     if (i > 0 && name.endsWith(".class") && name.substring(0, i).equals(packagePath)) 
     classes.add(Class.forName(name.substring(0, name.length() - 6).replace("/", "."))); 

     entry = stream.getNextJarEntry(); 
    } 

    stream.close(); 
    } 

    return classes; 
} 
+0

-1 brak dokumentacji, a nawet wskazówki na temat tego, co robi, +2, ponieważ wygląda na to, że skanuje ścieżkę klas i zawiera słoiki! więc zarabiasz +1 :) –

+0

(Cóż, nie było podpowiedzi, co robi .. Biorę to z powrotem). –

+0

Dodano nagłówek javadoc dla lepszego wyjaśnienia. :) – toluju

1

Powyższe odpowiedzi opisują wymaganą funkcjonalność. Jednak więcej szczegółów na ten temat można znaleźć here i here.

Powiązane problemy