Java 简明教程

Java - Module System

在 Java 9 中,引入了 Module system 来增强 Java 代码模块性。模块是包上的一种 abstraction 。此 module system 也称为 JPMS, Java Platform Module System 。它通常称为 Modules

What is a Module?

模块是代码和数据的自描述集合,并且有一个名称来对其进行标识。它是一种新型的编程组件,可以包含 packages 、特定于特定功能的配置和资源。模块能够限制对其所包含包的访问。默认情况下,模块中包内的代码对外部世界不可见,即使通过反射也无法访问。从 Java 9 开始,Java 平台本身就被模块化了。如果我们使用 list-modules 命令列出 Java 模块,它将打印 Java 支持的各种模块,如下所示:

C:\Users\Mahesh>java --list-modules
java.base@20.0.2
java.compiler@20.0.2
java.datatransfer@20.0.2
java.desktop@20.0.2
java.instrument@20.0.2
java.logging@20.0.2
java.management@20.0.2
java.management.rmi@20.0.2
java.naming@20.0.2
java.net.http@20.0.2
java.prefs@20.0.2
java.rmi@20.0.2
java.scripting@20.0.2
java.se@20.0.2
java.security.jgss@20.0.2
java.security.sasl@20.0.2
java.smartcardio@20.0.2
java.sql@20.0.2
java.sql.rowset@20.0.2
java.transaction.xa@20.0.2
java.xml@20.0.2
java.xml.crypto@20.0.2
jdk.accessibility@20.0.2
jdk.attach@20.0.2
jdk.charsets@20.0.2
jdk.compiler@20.0.2
jdk.crypto.cryptoki@20.0.2
jdk.crypto.ec@20.0.2
jdk.crypto.mscapi@20.0.2
jdk.dynalink@20.0.2
jdk.editpad@20.0.2
jdk.hotspot.agent@20.0.2
jdk.httpserver@20.0.2
jdk.incubator.concurrent@20.0.2
jdk.incubator.vector@20.0.2
jdk.internal.ed@20.0.2
jdk.internal.jvmstat@20.0.2
jdk.internal.le@20.0.2
jdk.internal.opt@20.0.2
jdk.internal.vm.ci@20.0.2
jdk.internal.vm.compiler@20.0.2
jdk.internal.vm.compiler.management@20.0.2
jdk.jartool@20.0.2
jdk.javadoc@20.0.2
jdk.jcmd@20.0.2
jdk.jconsole@20.0.2
jdk.jdeps@20.0.2
jdk.jdi@20.0.2
jdk.jdwp.agent@20.0.2
jdk.jfr@20.0.2
jdk.jlink@20.0.2
jdk.jpackage@20.0.2
jdk.jshell@20.0.2
jdk.jsobject@20.0.2
jdk.jstatd@20.0.2
jdk.localedata@20.0.2
jdk.management@20.0.2
jdk.management.agent@20.0.2
jdk.management.jfr@20.0.2
jdk.naming.dns@20.0.2
jdk.naming.rmi@20.0.2
jdk.net@20.0.2
jdk.nio.mapmode@20.0.2
jdk.random@20.0.2
jdk.sctp@20.0.2
jdk.security.auth@20.0.2
jdk.security.jgss@20.0.2
jdk.unsupported@20.0.2
jdk.unsupported.desktop@20.0.2
jdk.xml.dom@20.0.2
jdk.zipfs@20.0.2

C:\Users\Mahesh>

在这里我们可以看到,jdk 特定包在 jdk 模块中,而库特定包在 java 模块中。

Features of Java Module System

有了模块组件,以下增强已添加到 Java 9 中 −

  1. 引入了新的可选阶段 link time。此阶段介于编译时和运行时之间。在此阶段,可以使用 jlink 工具组装和优化一组模块,从而制作一个自定义的运行时映像。

  2. javacjlinkjava 具有指定模块路径的其他选项,可以进一步查找模块定义。

  3. JAR 格式被更新为模块化 JAR,它在根目录中包含 module-info.class 文件。

  4. 引入了 JMOD 格式,它是一种打包格式(类似于 JAR),可以包含本机代码和配置文件。

Declaring Module

为了声明模块,我们需要在应用程序的根文件夹中创建一个 module-info.java。此文件包含所有元数据或模块描述。

Example

module-info.java

module com.tutorialspoint.greetings {

}

Adding Dependent Modules

我们可以在模块中声明其他模块的依赖项。例如,如果我们想要使用 com.tutorialspoint.util 模块,则可以如下添加声明:

Example

module com.tutorialspoint.greetings {
   requires com.tutorialspoint.util;
}

Adding Optional Modules

我们可以使用模块中的 static 关键字来声明其他模块的可选依赖项。例如,如果我们想要使用 com.tutorialspoint.logging 模块,则可以如下添加声明:

Example

module com.tutorialspoint.greetings {
   requires com.tutorialspoint.util;
   requires static com.tutorialspoint.logging;
}

Adding Transitive Modules

我们可以使用模块中的 transitive 关键字来声明其他模块的传递依赖项。例如,如果我们想要使用 com.tutorialspoint.base 模块作为 com.tutorialspoint.util 模块的依赖项,则可以如下添加声明:

Example

module com.tutorialspoint.greetings {
   requires com.tutorialspoint.util;
   requires static com.tutorialspoint.logging;
   requires transitive com.tutorialspoint.base;
}

这意味着,如果一个模块想要使用 com.tutorialspoint.greetings,那么该模块也需要在模块声明中添加 com.tutorialspoint.base 模块。

Export Public Classes

默认情况下,模块的包中没有公共类会公开给外界。为了使用公共类,我们必须按如下所示对其进行导出:

Example

module com.tutorialspoint.greetings {
   requires com.tutorialspoint.util;
   requires static com.tutorialspoint.logging;
   requires transitive com.tutorialspoint.base;

   exports com.tutorialspoint.greetings.HelloWorld;
}

Allow Reflection

默认情况下,不能通过反射来访问模块的包中的任何私有成员。为了允许反射检查类或模块,我们必须按如下所示使用 opens 命令:

Example

module com.tutorialspoint.greetings {
   requires com.tutorialspoint.util;
   requires static com.tutorialspoint.logging;
   requires transitive com.tutorialspoint.base;

   exports com.tutorialspoint.greetings.HelloWorld;
   opens com.tutorialspoint.greetings.HelloWorld;
}

如果我们需要允许整个模块对反射开放,我们可以按如下所示使用 open 命令:

open module com.tutorialspoint.greetings {
   requires com.tutorialspoint.util;
   requires static com.tutorialspoint.logging;
   requires transitive com.tutorialspoint.base;

   exports com.tutorialspoint.greetings.HelloWorld;
}

Creating and Using Java Module

遵循这些步骤来创建一个名为 com.tutorialspoint.greetings 的模块。

Step 1

创建一个文件夹 C:\>JAVA\src。现在创建一个文件夹 com.tutorialspoint.greetings,该文件夹与我们创建的模块同名。

Step 2

在 C:\>JAVA\src\com.tutorialspoint.greetings 文件夹中使用以下代码创建 module-info.java。

module-info.java

module com.tutorialspoint.greetings { }

module-info.java 是用于创建模块的文件。在此步骤中,我们创建了名为 com.tutorialspoint.greetings 的模块。根据惯例,此文件应该驻留在名称与模块名称相同的文件夹中。

Step 3

在模块中添加源代码。在 C:\>JAVA\src\com.tutorialspoint.greetings\com\ tutorialspoint\greetings 文件夹中使用以下代码创建 Java9Tester.java。

Java9Tester.java

package com.tutorialspoint.greetings;

public class Java9Tester {
   public static void main(String[] args) {
      System.out.println("Hello World!");
   }
}

根据惯例,要位于该模块名称的同一目录中。

Step 4

创建文件夹 C:\>JAVA\mods。现在创建名称与我们创建的模块相同的文件夹 com.tutorialspoint.greetings。现在将模块编译到 mods 目录。

C:/ > JAVA > javac -d mods/com.tutorialspoint.greetings
   src/com.tutorialspoint.greetings/module-info.java
   src/com.tutorialspoint.greetings/com/tutorialspoint/greetings/Java9Tester.java

Step 5

让我们运行模块以查看结果。运行以下命令。

C:/>JAVA>java --module-path mods -m com.tutorialspoint.greetings/com.tutorialspoint.greetings.Java9Tester

此处 module-path 提供了模块位置为 mods,而 -m 表示主模块。

它将在控制台上打印以下输出。

Hello World!