总结
我无法跨模块边界反射性地实例化一个类。该类具有包级访问权限,我试图不仅从包外部实例化它,而且从模块本身外部实例化它。根据我的理解,我可以这样做,只要包含包已被包含模块打开
,并且实例化模块需要
包含模块.我尝试实例化得到的只是一个 IllegalAccessException
详情
我的应用程序在我的 Netbeans 11 中配置为“模块化 Java 项目”,并配置为在 Java 12 平台上运行。
在应用程序中,我有两个模块:
mod.world
mod.vehicles
mod.world
是我的“主要”模块——它有 main()
方法,并且声明它需要
其他模块 mod.vehicles
mod.vehicles
在包 vehicles.cars 中定义了一个名为
vehicles.cars.Sedan
的“ protected ”类(具有包级访问权限的类)
mod.vehicles
声明它打开 vehicles.cars
在 main()
方法中,我尝试实例化 Sedan
类,使用:
var myConstructor = Class.forName("vehicles.cars.Sedan").
getDeclaredConstructor();
myConstructor.newInstance();
我希望看到的
我希望代码成功实例化 Sedan
类,并执行 Sedan
构造函数中的 println()
。
我实际得到的
但是 newInstance()
的调用会抛出一个 IllegalAccessException
:
Exception in thread "main" java.lang.IllegalAccessException: class world.MyMainClass (in module mod.world) cannot access a member of class vehicles.cars.Sedan (in module mod.vehicles) with modifiers "public"
我的问题
根据Java Language Specification (第 7.7.2 节导出和打开的包):
The opens directive specifies the name of a package to be opened by the current module. For code in other modules, this grants access at run time, but not compile time, to the public and protected types in the package, and the public and protected members of those types. It also grants reflective access to all types in the package, and all their members, for code in other modules.
我对上述 JLS 摘录的理解是,我应该 能够访问“ protected ”类型
Sedan
及其成员, 其中包括构造函数。但为什么我不能使用它 构造函数以反射方式实例化Sedan
类?Java Language Specification的哪一部分我违反了吗 尝试这个实例化?
我对反射访问 一词的理解有误吗? Java 是否在某处正式定义了这个术语?在 Java 12 的 JLS 中的任何地方都找不到反射访问的正式定义。
完整代码如下:
mod.world
模块的 module-info.java
:
module mod.world {
exports world;
requires mod.vehicles;
}
MyMainClass.java
,在模块 mod.world
的包 world
中:
package world;
import java.lang.reflect.InvocationTargetException;
public class MyMainClass {
public static void main (String[] args) throws ClassNotFoundException,
NoSuchMethodException,
InstantiationException,
IllegalAccessException,
InvocationTargetException {
// This statement succeeds.
var myConstructor = Class.forName("vehicles.cars.Sedan").
getDeclaredConstructor();
// This statement throws IllegalAccessException
myConstructor.newInstance();
}
}
mod.vehicles
模块的 module-info.java
:
module mod.vehicles {
opens vehicles.cars;
}
Sedan.java
包 vehicles.cars
:
package vehicles.cars;
class Sedan {
public Sedan () {
System.out.println ("Inside constructor Sedan()");
}
}
其他观察
如果我将 Sedan
类更改为 public
类,则实例化会成功。
最佳答案
因为 Sedan
是包私有(private)的,你需要调用 myConstructor.setAccessible(true)
.
opens
是允许您调用 setAccessible
的,它并没有消除调用的需要。
关于java - 无法从另一个模块反射实例化 "protected"包的 "opened"类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57844936/