假设我有一个应用程序给出了一个众所周知的包名和类,我需要反射性地加载该类并从中调用一些方法。假设这个类在另一个java jar(“库”)中可用。
到目前为止,在java 9之前,因为类路径中的所有类都可用,所以直接实现这一点。
但是,对于Java 9,如果应用程序“module”不需要“library”包,则无法访问库类。
如何使用模块化罐子实现相同的行为?
示例:
这是我的申请:
// 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!
答案 0 :(得分:6)
有plenty of ways to make reflection work,但没有一个像&#34那样直接;它只是工作&#34;在模块系统之前的方式。让我根据你的具体问题缩小范围。
但在此之前,您必须确保库模块实际上将其放入模块图中。如果初始模块不能传递,则可以使用--add-modules library
将其添加到图表中。
你写的是#34;如果应用程序&#39;模块&#39;不需要&#39;库&#39;包,库类无法访问&#34;。假设你的意思是 module 而不是 package ,这是真的,但不适用于此处。可访问性基于两件事:
你没有写任何关于2.但是如果module library { exports org.reflection.lib; }
,那么你可以自由地使用反射。原因是当您开始使用反射API时会自动添加读取边缘。
现在它变得更有趣了。如果库模块未导出org.reflection.lib
或ReflectiveClass
未公开,则上述方法不起作用。在这种情况下,您有很多选择可供选择:
要了解他们的比较方式,请查看有关reflection vs encapsulation in Java 9的文章。
答案 1 :(得分:1)
如果第一个模块不通过requires
中的module-info.java
子句依赖于第二个模块,则第二个模块不在第一个模块的依赖关系的传递闭包中。因此,第二个模块无法观察到运行时,并且您的反射失败。在这种情况下,您可以通过--add-modules
选项将模块显式添加到模块图:
--add-modules <module-name>
在您的情况下,<module-name>
应替换为ReflectionLib
模块的名称。