Java 平台模块系统入门第 2 部分
介绍
在上一篇指南《Java 平台模块系统入门第 1 部分》中,我介绍了 Java 中的模块系统概念。在本指南中,我将向您展示更多使用模块的示例以及如何将ServiceLoader与模块一起使用。
使用模块
让我们将一个简单的图形界面作为另一个模块添加到我们的报价生成器中。
创建另一个顶级目录com.example.gui,其中包含以下类:
package com.example.gui;
import javafx.application.Application;
import javafx.scene.*;
import javafx.stage.Stage;
public class QuoteFxApp extends Application {
@Override
public void start(Stage primaryStage) throws Exception {
primaryStage.setTitle("Quotes");
Label label = new Label("A quote");
Scene scene = new Scene(label, 500, 200);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
Application.launch(args);
}
}
下一个module-info.java文件:
module com.example.gui {
}
当您执行javac来编译文件时:
javac -d out module-info.java com/example/gui/QuoteFxApp.java
会出现以下错误:
com\example\gui\QuoteFxApp.java:3: error: package javafx.application is not visible
import javafx.application.Application;
^
(package javafx.application is declared in module javafx.graphics, but module com.example.gui does not read it)
com\example\gui\QuoteFxApp.java:4: error: package javafx.scene is not visible
import javafx.scene.Scene;
^
(package javafx.scene is declared in module javafx.graphics, but module com.example.gui does not read it)
com\example\gui\QuoteFxApp.java:5: error: package javafx.scene.control is not visible
import javafx.scene.control.Label;
^
(package javafx.scene.control is declared in module javafx.controls, but module com.example.gui does not read it)
com\example\gui\QuoteFxApp.java:6: error: package javafx.stage is not visible
import javafx.stage.Stage;
^
(package javafx.stage is declared in module javafx.graphics, but module com.example.gui does not read it)
com\example\gui\QuoteFxApp.java:10: error: method does not override or implement a method from a supertype
@Override
^
5 errors
JavaFX 包不可见。我们需要引用模块javafx.graphics和javafx.controls。但为什么呢?
其背后的原因是 JDK 现在已经模块化,我们的应用程序需要声明它需要哪些 JDK 模块。
但是为什么我们在前面的例子中没有得到任何错误?我们没有得到任何错误,因为我们使用的类包含在java.base模块中,该模块默认添加到所有模块化应用程序中。
请注意,这仅发生在模块化应用程序中。Java 9 向后兼容;如果您的应用程序不包含module-info.java文件,则一切都将像以前版本的 Java 一样工作。如果您在没有module-info.java的情况下编译应用程序,您会发现不会抛出任何错误:
javac -d out com/example/gui/QuoteFxApp.java
但是在工作模块时,我们需要在module-info.java中要求应用程序所需的 JavaFX 模块:
module com.example.gui {
requires javafx.controls;
}
这次,javac将成功执行。
但是,请注意,我们只需要javafx.controls,而不是错误消息中提到的javafx.graphics 。
这是因为如果您使用javafx.controls模块,很可能也会使用javafx.graphics,因此javafx.controls将此模块声明为传递依赖项:
module javafx.controls {
...
requires transitive javafx.graphics;
...
}
当然,您可以明确将需要 javafx.graphics添加到您的module-info.java文件中,但这不是必需的,您可以自动获取它。
顺便说一下,如果要查看 JDK 的所有模块,JDK 安装目录中有一个名为jmods 的子目录。为了方便,我们可以使用jmod工具列出这些 JMOD 文件的内容。
在我的 Windows 机器上,要查看javafx.controls模块的详细信息,我执行:
jmod describe "C:\Program Files\Java\jdk-9\jmods\javafx.controls.jmod"
继续,我们的问题还没有解决。如果我们使用以下命令运行该程序:
java --module-path out --module com.example.gui/com.example.gui.QuoteFxApp
我们会得到以下错误:
java.lang.IllegalAccessException: class com.sun.javafx.application.LauncherImpl (in module javafx.graphics) cannot access class com.example.gui.QuoteFxApp (in module com.example.gui) because module com.example.gui does not export com.example.gui to module javafx.graphics
JavaFX 需要访问我们的类QuoteFxApp,因此我们需要通过以下方式导出包com.example.gui来明确授予访问权限:
module com.example.gui {
...
exports com.example.gui;
}
但是,这只是 JavaFX 的工作方式,我们可能不希望任何其他模块访问我们的包。对于这种情况,我们可以使用合格的导出:
module com.example.gui {
...
exports com.example.gui to javafx.graphics;
}
这样,只有列出的模块(在本例中只有javafx.graphics)可以访问包com.example.gui。我们的应用程序现在应该可以工作了:
了解了如何需要/导出其他模块后,集成编程报价模块和 GUI 模块应该很容易。
首先,在模块com.example.programming中,导出其包:
module com.example.programming {
exports com.example.programming;
}
编译这些类并再次将其打包为 JAR 文件。我们可以将此 JAR 复制到lib目录中以方便访问。
接下来,修改类QuoteFxApp以使用ProgrammingQuotes:
...
import com.example.programming.ProgrammingQuotes;
...
public class QuoteFxApp extends Application {
@Override
public void start(Stage primaryStage) throws Exception {
...
Label label = new Label(new ProgrammingQuotes().getQuote());
...
}
...
}
需要com.example.programming模块:
module com.example.gui {
...
...
}
使用模块路径选项编译com.example.gui模块,以便它可以找到com.example.programming模块(在本例中,它位于lib目录中):
javac -d out --module-path ../lib module-info.java com/example/gui/QuoteFxApp.java
最后,再次使用模块路径运行应用程序(请记住,Windows 的路径分隔符是;。对于 Linux/Mac使用: ):
java --module-path out;../lib --module com.example.gui/com.example.gui.QuoteFxApp
请注意,如果从模块路径中省略lib目录,则应用程序将无法运行:
java --module-path out --module com.example.gui/com.example.gui.QuoteFxApp
Error occurred during initialization of boot layer
java.lang.module.FindException: Module com.example.programming not found, required by com.example.gui
这在一定程度上解决了 JAR/classpath 地狱问题。
通过 S
免责声明:本内容来源于第三方作者授权、网友推荐或互联网整理,旨在为广大用户提供学习与参考之用。所有文本和图片版权归原创网站或作者本人所有,其观点并不代表本站立场。如有任何版权侵犯或转载不当之情况,请与我们取得联系,我们将尽快进行相关处理与修改。感谢您的理解与支持!
请先 登录后发表评论 ~