java - 无法从另一个模块反射实例化 "protected"包的 "opened"类

标签 java reflection java-module java-platform-module-system

总结

我无法跨模块边界反射性地实例化一个类。该类具有包级访问权限,我试图不仅从包外部实例化它,而且从模块本身外部实例化它。根据我的理解,我可以这样做,只要包含包已被包含模块打开,并且实例化模块需要包含模块.我尝试实例化得到的只是一个 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.

  1. 我对上述 JLS 摘录的理解是,我应该 能够访问“ protected ”类型 Sedan 及其成员, 其中包括构造函数。但为什么我不能使用它 构造函数以反射方式实例化 Sedan 类?

  2. Java Language Specification的哪一部分我违反了吗 尝试这个实例化?

  3. 我对反射访问 一词的理解有误吗? 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.javavehicles.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/

相关文章:

java 10 gradle 项目 : automatic module not found

java - Android 将页脚添加到 ListView addFooterView()?

java - 如何从 Thread 更新 java GUI?

java - 随机数猜谜游戏的逻辑错误

c# - 如何获得具有 out 参数的方法?

java - 如何通过检查找到返回类型的参数化类型?

java - 为什么java中不允许这种downcast?

java - 使用反射的非虚方法调用

Java 9 重叠的非导出包

java - java模块的springframework ldap核心问题