有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

Java 9:不需要“打开”模块以通过反射进行访问?

Java模块逻辑中的opens关键字允许反射访问(here)。我最近移植了一个复杂的JavaFX应用程序。Java15取得了成功,但这是一场噩梦,因为JavaFX正确地基于反射访问

我的问题是关于一个更简单的Java 15应用程序的,它可以完美地运行,但是我预期会出现一个运行时错误,而不会发生!为什么?任何亮点欢迎。。。因此,我在两个模块之间有一个非常常见的客户机/服务器关系,如下所示:

module PauWare2 {
   exports com.pauware.pauware_engine.Core;
}

module My_device_module {
   requires PauWare2;
}

人们可能会注意到opensMy_device_module中没有使用。实际上,PauWare2通过反射访问公共方法:

package My_device_package;

public class My_device { // In 'My_device_module'
   public void a() {}
   com.pauware.pauware_engine.Core.AbstractStateMachine _My_device_state_machine;
   // Reflective access of 'a' method by '_My_device_state_machine':
  _My_device_state_machine.launchByReflection(this, "a");
}

我预期会出现运行时错误,它涉及opens My_device_package to PauWare2;中的My_device_module?然而,如前所述,一点问题都没有。。。你知道吗?提前谢谢


共 (1) 个答案

  1. # 1 楼答案

    与Java语言规范相比:

    7.7.2. Exported and Opened Packages

    The exports directive specifies the name of a package to be exported by the current module. For code in other modules, this grants access at compile time and run time to the public and protected types in the package, and the public and protected members of those types (§6.6). It also grants reflective access to those types and members for code in other modules.

    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.

    所以opens指令的重点是而不是它授予反射访问权,exports也这样做。使用opens而不是exports的目的不是授予编译时访问权,这意味着运行时只有反射访问权是可能的

    因此,无论如何导出包时,不需要额外的opens。这意味着,如果你可以直接访问某个东西,你也可以反射地访问它

    或者,按照规范的字面意思,不是通过编译标准Java源代码生成的类文件可以在运行时访问打开的类型和成员


    你链接的这篇文章是关于“深度反思”的,通过调用^{}可以访问某个成员。但就连引用的文件也说:

    This method may be used by a caller in class C to enable access to a member of declaring class D if any of the following hold:

    • C and D are in the same module.
    • The member is public and D is public in a package that the module containing D exports to at least the module containing C.
    • The member is protected static, D is public in a package that the module containing D exports to at least the module containing C, and C is a subclass of D.
    • D is in a package that the module containing D opens to at least the module containing C. All packages in unnamed and open modules are open to all modules and so this method always succeeds when D is in an unnamed or open module.

    因此,第二个项目符号清楚地表明,对于导出包的public类型的public成员,也可以使用setAccessible(true)

    相关差异将在下一节中介绍:

    This method cannot be used to enable access to private members, members with default (package) access, protected instance members, or protected constructors when the declaring class is in a different module to the caller and the package containing the declaring class is not open to the caller's module.

    因此,它只会对非public成员产生影响,尤其是private和默认(包)访问