Java 获取类路径中的所有类

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3222638/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 17:32:25  来源:igfitidea点击:

Get all of the Classes in the Classpath

javareflectionclass

提问by arash

How can I get list of all available classes in CLASSPATHat runtime?
In Eclipse IDE, you can do this by pressing Ctrl+Shift+T.
Is there any method in Java to get it done?

如何CLASSPATH在运行时获取所有可用类的列表?
在 Eclipse IDE 中,您可以通过按Ctrl+ Shift+来执行此操作T
Java中有什么方法可以完成它吗?

采纳答案by BalusC

You can get all classpath roots by passing an empty Stringinto ClassLoader#getResources().

您可以通过将空传递StringClassLoader#getResources().

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

You can construct a Filebased on URLas follows:

您可以构建一个File基于URL如下:

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

You can use File#listFiles()to get a list of all files in the given directory:

您可以使用File#listFiles()获取给定目录中所有文件的列表:

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

You can use the standard java.io.Filemethods to check if it's a directory and/or to grab the filename.

您可以使用标准java.io.File方法来检查它是否是目录和/或获取文件名。

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.
}

Depending on the sole functional requirement, I guess that the Reflections libraryis much more exactly what you want.

根据唯一的功能需求,我想Reflections 库更符合您的需求。

回答by Bill K

Every so-often I look for this. It's kind of difficult because even if you manage to find everything on the classpath, you might not find everything available to a given class loader (for instance, I worked on a project that loaded class definitions directly from a DB once).

我经常找这个。这有点困难,因为即使您设法在类路径上找到所有内容,您也可能无法找到给定类加载器可用的所有内容(例如,我曾参与过一个直接从 DB 加载类定义的项目)。

The best bet at this point is probably to look into Spring. They scan the classes on the classpath to see if any have annotations that they need to kickstart stuff.

此时最好的选择可能是研究 Spring。他们扫描类路径上的类以查看是否有任何需要启动的注释。

The accepted answer here is a good place to start:

这里接受的答案是一个很好的起点:

Scanning Java annotations at runtime

在运行时扫描 Java 注释

回答by Andy

Here's what I wrote to do it. I'm sure it doesn't get everything if you're doing anything weird with the classpath, but it seems to work well for me. Note that it doesn't actually load the classes, it just returns their names. This is so that it won't load all classes into memory, and because some classes in my company's codebase were causing initialization errors if loaded at the wrong time...

这是我写的内容。我敢肯定,如果您对类路径做了任何奇怪的事情,它不会得到一切,但它似乎对我来说效果很好。请注意,它实际上并不加载类,它只是返回它们的名称。这是为了它不会将所有类加载到内存中,并且因为如果在错误的时间加载,我公司代码库中的某些类会导致初始化错误......

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();
    }
}

To use it:

要使用它:

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
    }
});

回答by Matthew Wise

You can make use of utility classes from the com.google.common.reflectpackage from the Guava library. E.g. to get all classes in a particular package:

您可以使用com.google.common.reflect来自 Guava 库的包中的实用程序类。例如,获取特定包中的所有类:

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

This is concise however the same caveats as other answers describe, still apply, namely, that it will generally only find classes loaded by a 'standard' ClassLoader e.g. URLClassLoader.

这很简洁,但是与其他答案描述的相同警告仍然适用,即它通常只会找到由“标准”类加载器加载的类,例如URLClassLoader.