提问者:小点点

IllegalAccessException:无法访问类%C(在模块%M中),因为模块%M没有将%C导出到模块%N


我试图将Maven支持添加到现有的JavaFX项目中。

我从OpenJFX的入门指南开始,它教您如何用Maven编译和运行Hello World JavaFX应用程序。 在我完成之后,我将我的项目的文件粘贴到这个新项目中,并进行所需的更改。 我的文件夹结构大致是这样的:

src/main/
  java/
    org.openjfx/
      Main.java
      components/
      controllers/
  resources/org.openjfx/fxml/

要运行项目,我使用以下Maven命令:

compiler:compile
javafx:compile
javafx:run

但是,我得到了这个错误:

应用程序启动方法中的异常,原因是:java.lang.IllegalAccessException:类javafx.fxml.fxmlLoader$ValueElement(在模块javafx.fxml中)无法访问类org.openjfx.Controllers.LoginController(在模块org.openjfx中),因为模块org.openjfx没有将org.openjfx.Controllers导出到模块javafx.fxml

这看起来很奇怪,因为显然我正在导出module-info.java中的内容:

module org.openjfx {
    requires javafx.controls;
    requires javafx.fxml;

    opens org.openjfx to javafx.fxml;
    exports org.openjfx;
}

我想知道将我的包命名为org.openjfx是不是一个坏主意,可能会引起问题,但我只是按照教程进行了操作。

下面是我的pom.xml文件,如果它相关的话:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>org.openjfx</groupId>
    <artifactId>hellofx</artifactId>
    <version>1.0-SNAPSHOT</version>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.release>11</maven.compiler.release>
        <javafx.version>13</javafx.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-controls</artifactId>
            <version>${javafx.version}</version>
        </dependency>
        <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-fxml</artifactId>
            <version>${javafx.version}</version>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                <configuration>
                    <release>${maven.compiler.release}</release>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.openjfx</groupId>
                <artifactId>javafx-maven-plugin</artifactId>
                <version>0.0.3</version>
                <configuration>
                    <mainClass>org.openjfx.App</mainClass>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

共1个答案

匿名用户

javafx.fxml模块实例化控制器类,并通过反射访问其中的字段和方法。 为了使其工作,您需要打开包含javafx.fxml模块的任何控制器的特定包。

这是理解模块系统的一个很好的资源。 引述如下:

打开,打开,打开……到。 在Java 9之前,反射可以用来了解包中的所有类型以及类型的所有成员--甚至是它的私有成员--无论您是否希望允许这种能力。 因此,没有任何东西被真正封装。

模块系统的一个关键动机是强大的封装性。 默认情况下,模块中的类型不能被其他模块访问,除非它是公共类型并且您导出了它的包。 只公开要公开的包。 对于Java 9号,这也适用于反思。

。。。

允许特定模块仅在运行时访问包。 表单的打开…到模块指令

opens package to comma-separated-list-of-modules 

指示特定包的公共类型(及其嵌套的公共类型和受保护类型)仅在运行时可由所列模块中的代码访问。 通过对指定模块中代码的反射,可以访问指定包中的所有类型(以及所有类型的成员)。

请注意,您打开的是包,而不是模块。 由于您的控制器位于子包org.openjfx.controllers中(我确实认为您应该更改您的基本包名称),因此您需要显式地打开该子包(可能还有其他子包)。

因此,添加

opens org.openjfx.controllers to javafx.fxml ;

module-info.java文件应该可以修复该问题