Java 9 揭秘(3. 创建你的第一个模块)

澳门新葡亰3522平台游戏 8

运行模块化代码

只是编译的话并没有多大乐趣。我们希望应用程序能够运行起来。幸运的是,JRE
和 JDK
已经在这个原型中支持模块关联。这个应用可以通过指定模块路径的方式来启动,而不是类路径:

java -mp mods -m module1/com.test.TestClassModule1

我们把模块路径指向 mods 文件夹,这个文件就是 javac
编译时写输出模块的地方。而 -m
指出了最初要启动的模块,通过这个模块可以逐步启动其他模块。我们同样添加了在初始化时需要调用的启动类的名字,运行结果如下所示:

Hi from from module 2!

5. 运行程序

使用java命令来运行Java程序。 语法如下:

java --module-path <module-path> --module <module>/<main-class>

这里,是用于定位模块的模块路径。
--module选项指定要与其主类一起运行的模块。
如果您的模块化JAR包含主属性,则需要指定部分,并且将从模块化JAR读取。

Tips
可以分别使用-module-path-module选项的简写版本-p-m

以下命令在com.jdojo.intro模块中运行com.jdojo.intro.Welcome类。
当前的目录是C: Java9Revealed,并且模块化的JAR位于C: java9Revealedlibcom.jdojo.intro-1.0.jar。

C:Java9Revealed>java --module-path lib
 --module com.jdojo.intro/com.jdojo.intro.Welcome
Welcome to the Module System.
Module Name: com.jdojo.intro

输出表示程序已正确执行。
如果在模块代码打包到模块化JAR中时指定主类,则可以从命令中省略主类名称。
我们已经将com.jdojo.intro.Welcome类指定为此模块的主类,因此以下命令的作用与上一个相同:

C:Java9Revealed>java --module-path lib --module com.jdojo.intro
Welcome to the Module System.
Module Name: com.jdojo.intro

还可以指定包含模块代码的目录作为模块路径。
已将模块代码编译到mods目录中。 以下命令的工作原理相同:

C:Java9Revealed>java --module-path mods
 --module com.jdojo.intro/com.jdojo.intro.Welcome
Welcome to the Module System.
Module Name: com.jdojo.intro

我们尝试从mods目录运行模块,只使用模块名称:

C:Java9Revealed>java --module-path mods --module com.jdojo.intro
module com.jdojo.intro does not have a MainClass attribute, use -m <module>/<main-class>

收到一个错误。
错误消息指示在modscom.jdojo.intro目录中找到的module-info.class不包含主类名称。当声明模块时,不能在模块声明中指定主方法或版本。
编译模块时,只能指定模块版本。
使用jar工具打包时,可以指定模块的主类及其版本。
libcom.jdojo.intro-1.0.jar中的module-info.class文件包含主类名,而modscom.jdojo.intro目录中的module-info.class文件则不包含。
如果要运行其编译代码位于分解目录中的模块,则必须指定主类名称以及模块名称。

JDK还提供了-jar选项来从JAR文件运行主类。 我们使用以下命令运行此模块:

C:Java9Revealed>java -jar libcom.jdojo.intro-1.0.jar
Welcome to the Module System.
Module Name: null

看来只有输出中的第一行是正确的,第二行是不正确的。
它找到了main()方法中执行了代码。 它正确打印消息,但模块名称为空。

需要了解JDK 9中java命令的行为。-jar选项存在于JDK 9之前。在JDK
9中,类型作为模块的一部分,可以通过模块路径或类路径加载。如果通过类路径加载类型,则该类型成为未命名模块的成员。该类型从其原始模块中失去其成员资格,即使该类型是从模块化JAR加载的。实际上,如果一个模块化的JAR放置在类路径上,那么它被视为一个JAR(而不是一个模块化的JAR),忽略它的module-info.class文件。每个应用程序类加载器都有一个未命名的模块。类加载器从类路径加载的所有类型都是该类加载器的未命名模块的成员。一个未命名的模块也被表示为一个Module类的实例,该类的getName()方法返回null。

在上一个命令中,模块化JAR
com.jdojo.intro-1.0.jar被视为一个JAR,并在其中定义了所有类型
,被加载为类加载器的未命名模块的一部分。这就是为什么在输出中将模块名称设为null的原因。

java命令如何找到主类名?为jar工具指定主类名时,该工具将主类名称存储在两个位置:

  • module-info.class
  • META-INF/MANIFEST.MF

该命令从META-INF/MANIFEST.MF文件读取主类的名称。

还可以使用--class-path选项的java命令来运行Welcome类。
可以将libcom.jdojo.intro-1.0.jar模块放置在类路径上,在这种情况下,它将被视为JAR,Welcome类将被加载到应用程序类加载器的未命名模块中。
就像在JDK 9之前运行类一样。执行命令如下:

C:Java9Revealed>java --class-path libcom.jdojo.intro-1.0.jar
  com.jdojo.intro.Welcome
Welcome to the Module System.
Module Name: null

为什么要使用模块?

什么是模块?我们为什又需要它们?如果希望有一个深入的讨论,请阅读“State
of the module system”或者看一下我们的报告。对这块还不是很了解的人来说,这里有Cliff
的注释版本。

我们都知道 Java 有 jar
文件。但是,事实上这些都只是包含一些class(类)的压缩文件,这些 jar
包内部都是一些 package (包)。当你利用一些不同的 jar
包来运行应用程序的时候(复杂一点的程序也适用),你需要把它们放到指定的类路径中。然后默默祈祷。因为没有有效的工具来帮助你知道,你是否已经把应用所需要的
jar 包都放入类路径中了。或者有可能你在不经意间将同样的类文件(在不同的
jar 包中)都放入了类路径中。类路径灾难(类似于 DLL
灾难)是真实存在的。这会导致运行时出现糟糕的状况。同时,在运行时我们也无法得知
jar 中包含哪些类。从 JRE 角度来说只知道有一堆类文件。事实上 jar
包之间是相互依赖的,但目前还不能把这种依赖关系记录到数据文件中去。理想的情况是,你可以隐藏
jar 包中类文件具体的实现,只是提供一些公共的 API 。在 Java
中提出模块化系统就是为了解决这些问题的:

  • 模块成为首先要考虑的部分,它能够分装实现细节并且只暴露需要的接口。
  • 模块准确地描述了他们能够提供的接口,以及他们的需要部分(依赖)。由此,我们可以在开发的过程中弄清和处理依赖关系。

模块系统极大地提升了大型系统的可维护性、可靠性、安全性。至少 JDK
本身还缺少这样的系统。通过这样的模块系统,模块图能够自动地构建。这个图只包括了你的应用程序运行时所须要的模块。

3. 编译源代码

使用Java编译器javac命令来编译源代码并将编译的代码保存在C: java9Revealedmods目录下。
javac命令位于JDK_HOMEbin目录中。 以下命令编译源代码。
命令输入是一行,而不是三行:

C:Java9Revealed>javac -d mods --module-source-path src
 srccom.jdojo.intromodule-info.java
 srccom.jdojo.introcomjdojointroWelcome.java

注意,运行此命令时,C:Java9Revealed是当前目录。
-d mods选项告诉Java编译器将所有编译的类文件保存到mods目录下。
注意,正在从C:java9revealed目录运行命令,因此命令中的mods目录表示C:Java9Revealedmods目录。
如果需要,可以用-d C:Java9Revealedmods替换此选项。

第二个选项--module-source-path src指定src目录的子目录包含多个模块的源代码,其中每个子目录名称与包含源代码的子目录的模块名称相同
。 这个选项有一些含义:

  • 在src目录下,必须将模块的源文件保存在子目录下,该目录必须与模块命名相同。
  • Java编译器将镜像src目录下的目录结构,同时将生成的类文件保存在mods目录中。
    也就是说,com.jdojo.intro模块的所有生成的类文件将保存在包层次结构的modscom.jdojo.intro目录中。
  • 如果不指定此选项,生成的类文件将直接放在mods目录下。

javac命令的最后两个参数是源文件 —— 一个是模块声明,一个Welcome类。
如果javac命令成功运行,则在C:Java9Revealedmodscom.jdojo.intro目录下生成以下两个类文件:

  • module-info.class
  • comjdojointroWelcome.class

你完成了源代码的编译。

以下命令使用JDK
9之前存在的样式来编译com.jdojo.intro模块的源代码。它仅使用-d选项,该选项指定放置编译的类文件的位置。

C:Java9Revealed>javac -d modscom.jdojo.intro      srccom.jdojo.intromodule-info.java      srccom.jdojo.introcomjdojointroWelcome.java

第二个命令的输出与上一个命令的输出是相同的。
但是,如果要在一个命令中编译多个模块的源代码,并将编译的代码放在特定于模块的目录中,则不起作用。

使用javac--module-version选项,可以指定正在编译的模块的版本。
模块版本保存在module-info.class文件中。
以下命令将生成与上一个命令相同的一组编译文件,还在module-info.class文件中保存了1.0作为模块版本:

C:Java9Revealed>javac -d modscom.jdojo.intro
  --module-version 1.0
  srccom.jdojo.intromodule-info.java    
  srccom.jdojo.introcomjdojointroWelcome.java

如何确认javac命令在module-info.class文件中保存了模块版本?
您可以使用javap命令来解析Java类文件。
如果指定了一个module-info.class文件的路径,那么javap命令会在模块名称之后打印模块的定义,其中包含模块的版本(如果存在)。
如果模块版本存在,则打印的模块名称的格式为moduleName @ moduleVersion
运行以下命令以验证上一个命令记录的模块名称:

C:Java9Revealed>javap modscom.jdojo.intromodule-info.class
Compiled from "module-info.java"
module com.jdojo.intro@1.0 {
  requires java.base;
}

在JDK 9中增强了jar工具。它允许在创建模块化JAR时指定模块版本。

如果要编译多个模块,则需要将每个源文件指定为javac命令的参数。
这里提供一个Windows和UNIX的快捷命令来一次性编译所有的模块。
在Windows中的一行中使用以下命令:

C:Java9Revealed>FOR /F "tokens=1 delims=" %A in ('dir src*.java /S /B') do javac -d mods --module-source-path src %A

该命令循环遍历src目录下的所有”.java”文件,并一次编译一个Java文件。

如果将命令保存在批处理文件中并运行批处理文件来编译所有源文件,则需要将%A替换为%%A
该命令的UNIX系统中等价于如下命令:

$ javac -d mods --module-source-path src $(find src -name "*.java")

一个简单的例子

你仍旧可以通过类、jar包以及类路径这样“传统方式”的方式来使用 JDK9
。但是明显地我们想要采用模块的方式。所以我们将创建一个包含两个模块的工程:模块一使用了模块二中的代码。

首先要做的就是,构建我们的工程并把两个模块很好地区分开来。然后,模块中需要以
module-info.java 文件的形式添加元数据。我们的示例构建如下:

src
  module1
     module-info.java
     comtestTestClassModule1.java
  module2
     module-info.java
     commoretestTestClassModule2.java

接着,我们将介绍 package (包)层最顶上的一层(module1、
module2),这部分你在之前已经构建好了。在这些“模块目录”中,可以看到
module-info.java
文件在根目录下。此外请注意,这两个类都是在显示命名的包中的。

请看 TestClassModule1 的代码:

package com.test;

import com.moretest.TestClassModule2;

public class TestClassModule1 {

   public static void main(String[] args) {

     System.out.println("Hi from " + TestClassModule2.msg());

   }

}

看起来很普通对吧?这里并没有涉及模块,而是导入了 TestClassModule2
,主函数之后会去调用其中的 msg() 方法。

package com.moretest;

public class TestClassModule2 {

   public static String msg() {

     return "from module 2!";

   }

}

到目前为止,module-info.java 还是空的。

本章介绍的程序非常简单。
当程序运行时,它打印一个消息和主类所属模块的名称。

安装 JDK9 预览版

如果你想亲自尝试编写示例代码,你需要安装包含 Jigsaw 原型的 JDK9
早期构建版本。在 OSX 上,你需要解压文档,然后把解压出来的目录移动到
Library/Java/JavaVirtualMachines/ 下。然后你需要设置环境变量,将
JAVA_HOME 环境变量指向 JDK9 的目录。我使用了非常好用的setjdk
脚本,通过它可以在命令窗口中实现 Java
安装的命令切换。你很有可能不愿意使用这个早期构建版本作为你的 Java
安装版本。你可以通过 java -version 来确认安装完成。输出如下面所示:

java version "1.9.0-ea"
Java(TM) SE Runtime Environment (build 1.9.0-ea-jigsaw-nightly-h3337-20150908-b80)
Java HotSpot(TM) 64-Bit Server VM (build 1.9.0-ea-jigsaw-nightly-h3337-20150908-b80, mixed mode)

只要输出中包含 Jigsaw ,你就可以继续了。文章后面的示例代码可以去
https://github.com/sandermak/jigsaw-firstlook下载。

2. 创建Java工程

选择“文件” ➤ “新建项目”,弹出对话框,选中“Java 应用程序”,然后下一步。

澳门新葡亰3522平台游戏 1

在接下来的窗口中,输入如下信息,你可以根据你自己的实际需要做出不同的调整。

澳门新葡亰3522平台游戏 2

项目名称:com.jdojo.intro
项目位置: C:Java9Revealed
取消下面两个复选框的。

点击“结束”按钮,Java工程创建完成。

澳门新葡亰3522平台游戏 3

创建Java项目时,NetBeans会创建一组标准的目录。
已在C: Java9Revealed目录中创建了com.jdojo.intro NetBeans项目。
NetBeans创建子目录来存储源文件,编译类文件和模块化JAR。
它将为项目本身创建安装目录和文件。
创建以下子目录来存储源代码,编译代码和模块化JAR。

C:Java9Revealed
    com.jdojo.intro
        build
           classes
        dist
        src

com.jdojo.intro目录保存此项目的所有类型的文件。
它是以NetBeans项目名称命名的。 src目录用于保存所有源代码。
build目录保存所有生成和编译的代码。
项目的所有编译代码保存在buildclasses目录下。 dist目录存储模块化JAR。
请注意,当类添加到项目时,build和dist目录是由NetBeans创建的。

对 Java 模块进行编译

现在进行下一步:编译我们的模块,并关联源文件。为了做这项工作,我们将介绍一个新的
javac 编译参数:

javac -modulesourcepath src -d mods $(find src -name '*.java')

使用上面语句时,我们假设命令程序已经处于 src
文件夹的上级目录中了。-modulesourcepath 参数会让 javac
从传统编译模式进入模块模式。-d 标记指出了编译好的模块的输出目录。javac
将以非打包文件的形式输出这些模块。如果我们这之后想以 jars
的形式使用这些模块的话,需要一个单独的步骤。

那么当我们调用上面的 javac
命令行的时候会发生什么那?编译出错了!

src/module1/module-info.java:1: error: expected 'module'
src/module2/module-info.java:1: error: expected 'module'

空的 module-info.java
文件导致了这个错误。所以,一些新的关键字将被引入到这些文件中来,这些都是模块中非常重要的部分。这些关键字的作用域就是
module-info.java 的定义部分。你还可以在 java 的源文件中使用 module
类型的变量。

我们采用了最少的描述信息,并更新了模块描述文件:

module module1 { }

然后是模块2:

module module2{ }

现在,模块已经被准确地命名了,但是还没有包含其它的数据。再次编译会导致新的错误:

src/module1/com/test/TestClassModule1.java:3: error: TestClassModule2 is not visible because package com.moretest is not visible

封装出现了!默认情况下,模块内部的类或者其他类型对外都是隐藏的。这就是
javac 不允许使用 TestClassModule2
的原因,即使它是一个公共的类。如果我们还是使用基于传统类路径的编译的话,一切都可以正常运作。当然我们也可以通过明确地将
TestClassModule2 暴露给外部来解决这个问题。接下来的这些改变对于 module2
中的 module-info.java 来说是必须的:

module module2 {

  exports com.moretest;

}

这还不够。如果你将修改后的编译,你会得到同样的错误。那是因为,虽然现在
module2 已经暴露了所需的包(包含所有的公共类型),但是 module1
还没有声明它对 module2 的依赖。我们同样可以改变 module1 的
module-info.java 文件来解决这个问题:

module module1 {

   requires module2;

}

通过指定名字的方法可以表示对其它模块的依赖,尽管在这些模块中是以包的形式导出的。这方面还有很多可以说的东西,但是我并不想在初步的介绍中涉及。在做完这一步之后,我们使用
Jigsaw 第一次成功编译了多模块项目。如果你打开 /mods
目录,你能看到编译出来的东西被整齐地划分为两个目录。这就成功了!

2. 编写源代码

你可以选择自己喜欢的文本编辑器(例如Windows上的记事本)来编写源代码。
首先创建一个名为com.jdojo.intro的模块。下面是模块声明的代码。

// module-info.java
module com.jdojo.intro {
    // No module statements
}

模块声明很简单。 它不包含模块语句。
将其保存在srccom.jdojo.intro目录下名为module-info.java的文件中。

然后创建一个名为Welcome的类,它将保存在com.jdojo.intro包中。
请注意,包的名字与模块具有相同的名称。 但必须保持模块和包名称相同吗?
答案是不。 也可以选择所需的任何其他包名称。
该类将具有一个主方法public status void main(String [] args)
该方法将作为应用程序的入口点。 在此方法内打印消息。

要打印模块的名称,Welcome 类是它的一个成员。 JDK
9在java.lang包中添加了一个名为Module的类。
Module类的一个实例代表一个模块。 JDK
9中的每个Java类型都是模块的成员,甚至是int,long和char等原始类型。
所有原始类型都是java.base模块的成员。 JDK
9中的Class类有一个名为getModule()的新方法,它返回该类作为其成员的模块引用。
以下代码打印了Welcome类的模块名称。

Class<Welcome> cls = Welcome.class;
Module mod = cls.getModule();
String moduleName = mod.getName();
System.out.format("Module Name: %s%n", moduleName);

Tips
所有原始数据类型都是java.base模块的成员。
可以使用int.class.getModule()获取int基本数据类型的模块的引用。

下面的代码包含是Welcome类中代码。并保存在名为Welcome.java的文件中,目录是comjdojointro,它是srccom.jdojo.intro目录的子目录。
此时,源代码文件的路径将如下所示:

  • C:Java9Revealedsrccom.jdojo.intromodule-info.java
  • C:Java9Revealedsrccom.jdojo.introcomjdojointroWelcome.java

// Welcome.java
package com.jdojo.intro;
public class Welcome {
    public static void main(String[] args) {
        System.out.println("Welcome to the Module System.");
        // Print the module name of the Welcome class
        Class<Welcome> cls = Welcome.class;
        Module mod = cls.getModule();
        String moduleName = mod.getName();
        System.out.format("Module Name: %s%n", moduleName);
    }
}

未来

这部分介绍可以让你初步了解可以使用 Java 9
中的模块可以做什么。这部分还是需要更多的探索。就像打包一样:除了jar包,即将会有一种新的形式叫做
jmod
。这个模块化系统同样包括一个服务层,它可以通过接口绑定服务提供者和服务使用者。可以把这个看成反转控制:模块系统担任服务注册管理的角色。还有一个值得期待的地方是,JDK
本身将会如何使用模块化系统进行模块化。这有可能支持一些非常棒的技术,比如创建一个运行时镜像,这个镜像可以只包括
JDK
和你应用所需要的那些模块。好处有:占用更少的空间,对于程序整体的优化可以有更多的选择等等。这些前景都是很光明的。

我接下来将尝试移植一个简单的 OSGi
应用程序(该程序会使用一些模块和服务)到 Java 9 模块系统上。敬请关注!

6. 编写源代码

在本节中,向com.jdojo.intro项目添加一个Welcome类。
该类保存在com.jdojo.intro包中。
右键单击项目,在弹出的菜单中,选择新建➤Java类,打开“新建Java类”对话框。
输入Welcome作为类名,com.jdojo.intro作为包。 单击完成按钮关闭对话框。

澳门新葡亰3522平台游戏 4

用下面的代码替换掉自动生成的代码。

package com.jdojo.intro;

public class Welcome {
      public static void main(String[] args) {
        System.out.println("Welcome to the Module System.");
        // Print the module name of the Welcome class
        Class<Welcome> cls = Welcome.class;
        Module mod = cls.getModule();
        String moduleName = mod.getName();
        System.out.format("Module Name: %s%n", moduleName);
    }
}

澳门新葡亰3522平台游戏 5

昨天,我和同事 Paul Bakker 在 JavaZone 上对于 Java 模块化系统进行了讨论。整个讨论都建立在JSR-376
需求文档以及身边一些珍贵的信息上。在年初提出举行这个报告的时候,我们曾深信不疑地认为在这个会上我们能够展示一个原型,但是事情却没有按预想的那样发展。现在的情况是,这个原型将在我们的报告结束之后发布。这也意味着,报告中的一些内容已经有点过时了,但是主要的思想还是很有新意的。如果你对
Java 模块化系统方案一无所知的话,建议你在阅读这篇文章之前先去看一下我们的报告。我们的报告介绍了现在的方案,并进一步与
OSGi 进行了比较。

三. 总结

使用模块开发Java应用程序不会改变Java类型被组织成包的方式。
模块的源代码在包层次结构的根目录下包含一个module-info.java文件。
也就是说,module-info.java文件放在未命名的包中。 它包含模块声明。

JDK 9中已经增强了javac编译器,jar工具和java启动器以与模块配合使用。
javac编译器接受新的选项,例如用于定位应用程序模块的--module-path,找到模块源代码的--module-source-path,以及--module-version来指定正在编译的模块的版本。
该jar工具允许分别使用--main-class-module-version选项为模块化JAR指定主类和模块版本。
java启动器可以在类路径模式,模块模式或混合模式下运行。
要在模块中运行类,需要使用--module-path澳门新葡亰3522平台游戏,选项指定模块路径。
需要使用--module选项指定主类名称。
主类以/格式指定,其中是包含主类的模块,是包含main()方法的类的完全限定名称,作为应用程序的执行入口。

在JDK 9中,每个类型都属于一个模块。
如果从类路径加载类型,它属于加载它的类加载器的未命名模块。 在JDK
9中,每个类加载器维护一个未命名的模块,其成员都是该类加载器从类路径加载的所有类型。
从模块路径加载的类型属于定义的模块。

Module类的一个实例在运行时表示一个模块。 Module类在java.lang包中。
使用Module类在运行时了解有关模块的所有内容。 Class类在JDK
9中得到了增强。它的getModule()方法返回一个表示此类成员的模块的模块实例。
Module类包含一个getName()方法,它以String形式返回模块的名称;
对于未命名的模块,该方法返回null。

NetBeans IDE正在更新,以支持JDK 9和开发模块化Java应用程序。
目前,NetBeans允许创建模块,编译,将其打包成模块化JAR,并从IDE中运行它们。
需要为模块创建一个单独的Java项目。
其最终版本将允许在一个Java项目中拥有多个模块。
支持添加module-info.java文件。 NetBeans
具有非常酷的功能,可查看和保存模块图。

Java 模块化系统自提出以来经历了很长的时间,直到 2014 年晚些时候才最终以
JSR(JSR-376) 定稿,而且这个部分有可能在 Java 9 中出现。但是一直以来都没有可以使用的原型。9
月 11 日,OpenJDK 发布的早期构建版本终于包含了 Jigsaw 项目。

8. 打包模块代码

需要构建项目,为你的模块创建一个模块化JAR。
选择“运行”➤“构建项目”,或按F11构建项目。
模块化的JAR是在dist目录下创建的。 模块化JAR以NetBeans项目名称命名。
com.jdojo.intro模块的模块化JAR将位于C:Java9Revealedcom.jdojo.introdistcom.jdojo.intro.jar。

目前,NetBeans不支持在模块化JAR中添加主类名称和模块版本名称。
可以使用jar命令行工具来更新模块化JAR中的模块信息。
使用--update选项,如下所示,要写在一行。

C:Java9Revealed>jar --update
  --file com.jdojo.introdistcom.jdojo.intro.jar
  --module-version 1.0
  --main-class com.jdojo.intro.Welcome

可以使用以下命令验证com.jdojo.intro的模块化JAR是否正确更新。
应该得到类似的输出:

C:Java9Revealed>java --module-path com.jdojo.introdist
  --list-modules com.jdojo.intro
module com.jdojo.intro@1.0 (file:///C:/Java9Revealed/com.jdojo.intro/dist/com.jdojo.intro.jar)
  requires mandated java.base (@9-ea)
  contains com.jdojo.intro

NetBeans IDE的最终版本将与JDK
9相同时间发布,到那时就允许通过IDE添加这些属性。

文 by / 林本托

在本章中,将介绍如何使用模块 —— 从编写源代码到编译,打包和运行程序。
本章分为两部分。 第一部分显示使用命令行编写和运行模块程序的所有步骤。
第二部分使用NetBeans IDE重复相同的步骤。

3. 设置工程属性

当前项目仍然设置为使用JDK 1.8。 需要将其更改为使用JDK
9。在项目上右键,弹出对话框。

澳门新葡亰3522平台游戏 6

再设置源/二进制格式:

澳门新葡亰3522平台游戏 7

最后点击“确定”按钮完整工程的配置。

5. 查看模块图

NetBeans IDE允许查看模块图。
在编辑器中打开模块的module-info.java文件,并在编辑器中选择“图形”选项卡以查看模块图。

澳门新葡亰3522平台游戏 8

可以放大和缩小模块图,更改其布局,并将其另存为图像。
在图区域中右键单击这些图形相关选项。
可以在图中选择一个节点,仅查看以节点结尾或从节点结尾的依赖关系。
还可以通过移动节点来重新排列模块图。

在这个章节中,主要介绍以下内容: