5

我需要main在模块内部还是外部运行我的方法?

我是使用 Java 模块化系统的新手。我正在尝试在 Java 10 中使用 JavaFX 创建一个简单的程序,因为它是支持 JavaFX 的最后一个 Java 版本。

我在我的 for JavaFX 上导入了必要的依赖module-info.java项,它只显示一个简单的窗口。

sample.fxml代码:

<?import javafx.scene.layout.GridPane?>
<GridPane fx:controller="com.gui.Controller"
          xmlns:fx="http://javafx.com/fxml" alignment="center" hgap="10" vgap="10">
</GridPane>

当我构建我的代码时,它说:

Warning:(4, 27) java: module not found: com.main

当我尝试运行我的代码时,我得到:

Exception in Application constructor Exception in thread "main" java.lang.reflect.InvocationTargetException
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:564)
    at java.base/sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:941)

任何人都可以为此提供建议,或者以某种方式提供有关使用模块化系统创建项目的真实世界应用程序建议。

我在下面附上了一对截图。

构建警告:

在此处输入图像描述

运行时失败:

在此处输入图像描述

4

3 回答 3

2

这里可能的怀疑是您正在使用com.main作为模块名称module-info.java,IDE 抱怨在项目中没有找到该名称。

我猜想,这可能会com.gui在声明中用作模块名称来解决。

于 2018-10-13T15:19:34.813 回答
1

模块系统增加了更强的封装性。换句话说,不再是所有类都可以反射地访问其他所有类的情况。

以通常的方式启动 JavaFX 时,Application会为您实例化一个子类的实例。这是通过反射完成的,这意味着负责实例化子类 ( javafx.graphics) 的模块必须具有使用公共、无参数构造函数实例化公共类所需的反射访问权限。要授予此访问权限,包含Application子类的模块必须至少有exports适当的包。 javafx.graphics

这在以下文档中有所描述Application

...

Application子类必须声明为公共的,并且必须有一个公共的无参数构造函数。

...

将应用程序部署为模块

如果Application子类位于命名模块中,则该模块必须可以访问该类javafx.graphics。否则,应用程序启动时会抛出异常。这意味着除了类本身被声明为公共之外,模块必须将包含的包导出(或打开)到至少该javafx.graphics模块。

例如,如果com.foo.MyApplication是在foo.app模块中,则module-info.java可能如下所示:

module foo.app {
    exports com.foo to javafx.graphics;
}

您似乎也在使用 FXML。如有必要,您必须确保可以反射访问适当的包javafx.fxml(例如控制器类)。这记录在FXML 简介中

将应用程序部署为模块

如果FXMLLoader用于在命名模块中加载类型,则应用程序必须确保 FXML 文件中引用的所有类型,包括控制器类和任何自定义Node类,都可以通过反射访问javafx.fxml模块。如果模块opens包含至少模块的包,则类型是反射式可访问的javafx.fxml

例如,如果com.foo.MyController是在foo.app模块中,则module-info.java可能如下所示:

module foo.app {
    opens com.foo to javafx.fxml;
}
于 2018-10-13T23:00:25.150 回答
0

我通过确保:

需要 javafx 依赖项的模块也会导出自身导致一些 javafx 包或模块需要需要它的模块。

前任。javafx.graphics

还要确保 fxml 资源是正确的。

1.) 修正 fxml 资源:

在此处输入图像描述

2.) 导出需要javafx依赖的模块:

错误:(读取)

Caused by: java.lang.IllegalAccessException: class com.sun.javafx.application.LauncherImpl (in module javafx.graphics) cannot access class com.gui.GUI (in module com.gui) because module com.gui does not export com.gui to module javafx.graphics
    at java.base/jdk.internal.reflect.Reflection.newIllegalAccessException(Reflection.java:360)
    at java.base/java.lang.reflect.AccessibleObject.checkAccess(AccessibleObject.java:589)
    at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:479)
    at javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$8(LauncherImpl.java:875)
    at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runAndWait$11(PlatformImpl.java:449)
    at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$9(PlatformImpl.java:418)
    at java.base/java.security.AccessController.doPrivileged(Native Method)
    at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$10(PlatformImpl.java:417)
    at javafx.graphics/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:96)
    at javafx.graphics/com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
    at javafx.graphics/com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:175)

解决方案 :module-info.java

module com.gui {
    requires javafx.graphics;
    requires javafx.fxml;
    exports com.gui;
}
于 2018-10-13T16:41:45.457 回答