主方法不在模块内部运行

时间:2018-10-13 15:03:07

标签: java javafx java-10 java-module

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

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

我为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)

有人可以给我建议吗,或者以某种方式为我提供有关使用模块化系统创建项目的实际应用建议。

我在下面附有一对屏幕截图。

构建警告:

enter image description here

运行时失败:

enter image description here

3 个答案:

答案 0 :(得分:2)

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

我想,可以使用com.gui作为声明中的模块名称来解决此问题。

答案 1 :(得分:1)

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

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

这在Application的{​​{3}}中进行了描述:

  

...

     

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

     

...

     

将应用程序部署为模块

     

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

     

例如,如果com.foo.MyApplicationfoo.app模块中,则module-info.java可能看起来像这样:

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

您似乎也正在使用FXML。如有必要,您必须确保javafx.fxml可以反射地访问相应的程序包(例如,控制器类)。 the documentation中对此进行了记录:

  

将应用程序部署为模块

     

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

     

例如,如果com.foo.MyControllerfoo.app模块中,则module-info.java可能看起来像这样:

module foo.app {
    opens com.foo to javafx.fxml;
}

答案 2 :(得分:0)

我通过确保解决此问题:

  

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

     

例如javafx.graphics

还要确保fxml资源正确。

1。)对fxml资源的修正:

enter image description here

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;
}