从包中获取所有类

Jus*_*wer 11 java reflection package

可以说我有一个java包commands,其中包含所有继承自的类,ICommand我能以某种方式得到所有这些类吗?我正在锁定以下内容:

Package p = Package.getPackage("commands");
Class<ICommand>[] c = p.getAllPackagedClasses(); //not real 
Run Code Online (Sandbox Code Playgroud)

有可能吗?

Bal*_*usC 15

这是一个基本的例子,假设类不是JAR打包的:

// Prepare.
String packageName = "com.example.commands";
List<Class<ICommand>> commands = new ArrayList<Class<ICommand>>();
URL root = Thread.currentThread().getContextClassLoader().getResource(packageName.replace(".", "/"));

// Filter .class files.
File[] files = new File(root.getFile()).listFiles(new FilenameFilter() {
    public boolean accept(File dir, String name) {
        return name.endsWith(".class");
    }
});

// Find classes implementing ICommand.
for (File file : files) {
    String className = file.getName().replaceAll(".class$", "");
    Class<?> cls = Class.forName(packageName + "." + className);
    if (ICommand.class.isAssignableFrom(cls)) {
        commands.add((Class<ICommand>) cls);
    }
}
Run Code Online (Sandbox Code Playgroud)

  • +1,虽然是一个很小的改进:`root.getFile()`应该是`URLDecoder.decode(root.getFile(),"UTF-8")`以防`classloader`路径中有任何空格.`getResource()`将它转换为'%20`,以及我想的其他字符. (3认同)

Pas*_*ent 6

下面是使用JSR-199 API的实现,即来自javax.tools.*以下类的类:

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

JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager fileManager = compiler.getStandardFileManager(
        null, null, null);

Location location = StandardLocation.CLASS_PATH;
String packageName = "commands";
Set<JavaFileObject.Kind> kinds = new HashSet<JavaFileObject.Kind>();
kinds.add(JavaFileObject.Kind.CLASS);
boolean recurse = false;

Iterable<JavaFileObject> list = fileManager.list(location, packageName,
        kinds, recurse);

for (JavaFileObject javaFileObject : list) {
    commands.add(javaFileObject.getClass());
}
Run Code Online (Sandbox Code Playgroud)

  • 实际上,您需要一个JDK来获取非`null`编译器对象(请参阅http://bit.ly/89HtA0),因此该API并不真正针对桌面.它应该在服务器端正常(大多数应用服务器毕竟使用JDK,例如用于JSP编译).但当然,可能有例外.实际上,我只是想表明JDK中有一些支持,即使这不是编译器API的完美用例(这里的用法很差).这个API可以做更多,更多,例如动态编译在内存中动态生成的Java源代码(已经更有趣). (2认同)
  • 当我运行这个 javaFileObject.getClass() 时,返回 javaFileObject 的类,即 com.sun.tools.javac.util.DefaultFileManager$RegularFileObject。该类不会重写 Object.getClass() (2认同)