it-swarm.com.de

Obter todas als Klassen no caminho de classe

Como posso obter uma lista de todas as classes disponíveis em CLASSPATH em tempo de execução?
Keine Eclipse-IDE, Você Pode Fazer Isso PressionandoCtrl+Shift+T.
Existe algum método em Java para fazê-lo?

40
arash

Sie können alle Klassenpfad-Wurzeln abrufen, indem Sie eine leere String in ClassLoader#getResources() übergeben.

Enumeration<URL> roots = classLoader.getResources("");

Sie können eine File basierend auf URL folgendermaßen erstellen:

File root = new File(url.getPath());

Sie können File#listFiles() verwenden, um eine Liste aller Dateien im angegebenen Verzeichnis zu erhalten:

for (File file : root.listFiles()) {
    // ...
}

Sie können die Standardmethoden Java.io.File verwenden, um zu prüfen, ob es sich um ein Verzeichnis handelt, und/oder um den Dateinamen abzurufen.

if (file.isDirectory()) {
    // Loop through its listFiles() recursively.
} else {
    String name = file.getName();
    // Check if it's a .class file or a .jar file and handle accordingly.
}

Abhängig von der einzigen funktionalen Anforderung schätze ich, dass die Reflections-Bibliothek viel genauer ist, als Sie möchten. 

52
BalusC

Hier ist, was ich geschrieben habe, um es zu tun. Ich bin mir sicher, dass es nicht alles bekommt, wenn Sie mit dem Klassenpfad seltsame Dinge tun, aber es scheint für mich gut zu funktionieren. Beachten Sie, dass die Klassen nicht wirklich geladen werden, sondern nur deren Namen zurückgegeben werden. Dies ist so, dass nicht alle Klassen in den Speicher geladen werden und weil einige Klassen in der Codebase meines Unternehmens Initialisierungsfehler verursacht haben, wenn sie zum falschen Zeitpunkt geladen wurden ...

public interface Visitor<T> {
    /**
     * @return {@code true} if the algorithm should visit more results,
     * {@code false} if it should terminate now.
     */
    public boolean visit(T t);
}

public class ClassFinder {
    public static void findClasses(Visitor<String> visitor) {
        String classpath = System.getProperty("Java.class.path");
        String[] paths = classpath.split(System.getProperty("path.separator"));

        String javaHome = System.getProperty("Java.home");
        File file = new File(javaHome + File.separator + "lib");
        if (file.exists()) {
            findClasses(file, file, true, visitor);
        }

        for (String path : paths) {
            file = new File(path);
            if (file.exists()) {
                findClasses(file, file, false, visitor);
            }
        }
    }

    private static boolean findClasses(File root, File file, boolean includeJars, Visitor<String> visitor) {
        if (file.isDirectory()) {
            for (File child : file.listFiles()) {
                if (!findClasses(root, child, includeJars, visitor)) {
                    return false;
                }
            }
        } else {
            if (file.getName().toLowerCase().endsWith(".jar") && includeJars) {
                JarFile jar = null;
                try {
                    jar = new JarFile(file);
                } catch (Exception ex) {

                }
                if (jar != null) {
                    Enumeration<JarEntry> entries = jar.entries();
                    while (entries.hasMoreElements()) {
                        JarEntry entry = entries.nextElement();
                        String name = entry.getName();
                        int extIndex = name.lastIndexOf(".class");
                        if (extIndex > 0) {
                            if (!visitor.visit(name.substring(0, extIndex).replace("/", "."))) {
                                return false;
                            }
                        }
                    }
                }
            }
            else if (file.getName().toLowerCase().endsWith(".class")) {
                if (!visitor.visit(createClassName(root, file))) {
                    return false;
                }
            }
        }

        return true;
    }

    private static String createClassName(File root, File file) {
        StringBuffer sb = new StringBuffer();
        String fileName = file.getName();
        sb.append(fileName.substring(0, fileName.lastIndexOf(".class")));
        file = file.getParentFile();
        while (file != null && !file.equals(root)) {
            sb.insert(0, '.').insert(0, file.getName());
            file = file.getParentFile();
        }
        return sb.toString();
    }
}

Um es zu benutzen:

ClassFinder.findClasses(new Visitor<String>() {
    @Override
    public boolean visit(String clazz) {
        System.out.println(clazz)
        return true; // return false if you don't want to see any more classes
    }
});
17
Andy

Sie können Dienstprogrammklassen aus dem Paket com.google.common.reflect aus der Guava-Bibliothek verwenden. Z.B. Um alle Klassen in einem bestimmten Paket zu erhalten:

    ClassLoader cl = getClass().getClassLoader();
    Set<ClassPath.ClassInfo> classesInPackage = ClassPath.from(cl).getTopLevelClassesRecursive("com.mycompany.mypackage");

Dies ist zwar prägnant, jedoch gelten die gleichen Vorbehalte, wie sie in anderen Antworten beschrieben werden, und zwar immer noch, nämlich dass im Allgemeinen nur Klassen gefunden werden, die von einem "Standard" ClassLoader geladen werden, z. URLClassLoader.

7
Matthew Wise

Ich suche immer so oft. Das ist ziemlich schwierig, denn selbst wenn Sie alles im Klassenpfad finden, finden Sie möglicherweise nicht alles, was einem bestimmten Klassenladeprogramm zur Verfügung steht (z. B. habe ich an einem Projekt gearbeitet, das Klassendefinitionen direkt aus einer Datenbank geladen hat).

Die beste Wette zu diesem Zeitpunkt ist wahrscheinlich der Blick in den Frühling. Sie durchsuchen die Klassen im Klassenpfad, um zu sehen, ob sie Anmerkungen haben, die sie zum Kickstart benötigen.

Die akzeptierte Antwort hier ist ein guter Ausgangspunkt:

Java-Anmerkungen zur Laufzeit scannen

0
Bill K

Ich schlage vor, Spring's PathMatchingResourcePatternResolver zu verwenden.

Es ist der Trick für das Starten des Pakets sowohl von einer IDE als auch vom Dateisystem aus:

Für mehr Details schau hier meine Notiz:

So erhalten Sie Ressourcen aus einem Paket

0
Naor Bar