Java9中的java如果我不知道类的模块,如何反射地加载它?
假设我有一个应用程序,给定了一个众所周知的包名和类,我需要反射地加载该类,并从中调用一些方法。假设这个类在另一个java jar(“库”)中可用
到目前为止,在Java9之前,由于类路径中的所有类都是可用的,所以实现这一点很简单
但是,在Java 9中,如果应用程序“模块”不需要“库”包,则无法访问库类
如何使用模块化的JAR实现相同的行为
例如:
这是我的申请表:
// This is defined in ReflectionApp.jar
// ReflectionApp
// └── src
// ├── module-info.java
// └── org
// └── reflection
// └── app
// └── ReflectionApp.java
//
package org.reflection.app;
import java.lang.reflect.Method;
public class ReflectionApp {
private static final String PACKAGE = "org.reflection.lib";
private static final String CLASS = "ReflectiveClass";
private static final String METHOD = "doSomeWork";
public static void main(String[] args) throws Exception {
// This will not work using java9
Class<?> klass = Class.forName(String.format("%s.%s", PACKAGE, CLASS));
Object obj = klass.getDeclaredConstructor().newInstance();
Method meth = klass.getDeclaredMethod(METHOD);
meth.invoke(obj);
}
}
这是我的图书馆
// This is defined in ReflectionLib.jar
// ReflectionLib
// └── src
// ├── module-info.java
// └── org
// └── reflection
// └── lib
// └── ReflectiveClass.java
//
package org.reflection.lib;
public class ReflectiveClass {
public void doSomeWork() {
System.out.println("::: Doing some work!");
}
}
现在,如果我试着这样称呼它(假设所有JAR都已创建并在lib目录中可用):
java --module-path lib -m ReflectionApp/org.reflection.app.ReflectionApp
然后我得到一个Exception in thread "main" java.lang.ClassNotFoundException: org.reflection.lib.ReflectiveClass
---解决方案---
多亏了@Nicolai,我才能够通过在命令中添加--add-modules
参数来运行它
⇒ java --module-path lib --add-modules ReflectionLib -m ReflectionApp/org.reflection.app.ReflectionApp
::: Doing some work!
# 1 楼答案
有plenty of ways to make reflection work但是没有一个像模块系统之前的“it just works”方式那样直截了当。针对你的特殊问题,让我把范围缩小
但在此之前,您必须确保库模块实际进入模块图。如果初始模块不需要它,可以使用
add-modules library
将其添加到图形中出口包装
您写道“如果应用程序‘模块’不需要‘库’包,则库类不可访问”。假设你的意思是模块而不是包,这是正确的,但不适用于这里。可访问性建立在两个方面:
你没有写任何关于2的东西。但是如果
module library { exports org.reflection.lib; }
,那么你可以自由地使用反射。原因是,当您开始使用反射API时,读取边缘会自动添加无法访问的类型
现在它变得更有趣了。如果库模块不导出
org.reflection.lib
,或者ReflectiveClass
不是公共的,则上述方法不起作用。在这种情况下,你有很多选择:看看这篇关于reflection vs encapsulation in Java 9的文章,看看它们是如何比较的
# 2 楼答案
如果第一个模块通过
module-info.java
中的requires
子句不依赖于第二个模块,那么第二个模块不在第一个模块依赖项的传递闭包中。因此,运行时无法观察到第二个模块,并且反射失败。在这种情况下,您可以通过add-modules
选项将模块显式添加到模块图中:在您的例子中
<module-name>
应该被ReflectionLib
模块的名称替换