专业的JAVA编程教程与资源

网站首页 > java教程 正文

JAVA9 模块系统的使用(java9特性介绍)

temp10 2024-09-11 09:15:44 java教程 11 ℃ 0 评论

什么是模块系统

Java 9 最大的变化之一是引入了模块系统(Jigsaw 项目)。

模块就是代码和数据的封装体。模块的代码被组织成多个包,每个包中包含Java类和接口;模块的数据则包括资源文件和其他静态信息。

JAVA9 模块系统的使用(java9特性介绍)

Java 9 模块的重要特征是在其工件(artifact)的根目录中包含了一个描述模块的 module-info.class 文 件。 工件的格式可以是传统的 JAR 文件或是 Java 9 新增的 JMOD 文件。这个文件由根目录中的源代码文件 module-info.java 编译而来。该模块声明文件可以描述模块的不同特征。

为什么要使用模块化

java开发者都知道,使用java开发应用程序都会遇到一个问题,Jar hell,他就像windows里的dll hell。

比如我们启动一个不算大的应用,但依赖了很多的jar,如下图:

摘自:Mark Reinhold的演讲 www.youtube.com/watch?v=l1s…

这是很常见的。虽然你可以使用 "java -Djava.ext.dirs=lib xxx" 让命令行小一些,但不可否认,他的classpath就是那么长。顺便说一句,java9中不允许使用extdirs了。

另一方面,jdk本身有很多的api:

如何使用模块系统

在 module-info.java 文件中,我们可以用新的关键词module来声明一个模块,如下所示。下面给出了一个模块com.mycompany.mymodule的最基本的模块声明。

module com.runoob.mymodule {
}

创建模块

接下来我们创建一个 com.runoob.greetings 的模块。

第一步

创建文件夹 /home/xx/JAVA/src,然后在该目录下再创建与模块名相同的文件夹 com.runoob.greetings。

第二步

在 /home/xx/JAVA/src/com.runoob.greetings 目录下创建 module-info.java 文件,代码如下:

module com.runoob.greetings { }

module-info.java 用于创建模块。这一步我们创建了 com.runoob.greetings 模块。

第三步

在模块中添加源代码文件,在目录 /home/xx/JAVA/src/com.runoob.greetings\com\runoob\greetings 中创建文件 Java9Tester.java,代码如下:

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

第四步

创建文件夹 /home/xx/JAVA/src/,然后在该目录下创建 com.runoob.greetings 文件夹,编译模块到这个目录下:

 javac -d mods/com.runoob.greetings 
 src/com.runoob.greetings/module-info.java 
 src/com.runoob.greetings/com/runoob/greetings/Java9Tester.java

第五步

执行模块,查看输出结果:

C:/>JAVA> java --module-path mods -m com.runoob.greetings/com.runoob.greetings.Java9Tester
Hello World!

module-path 指定了模块所在的路径。

-m 指定主要模块。

內建的module

jdk原生的包被归并到內建的module里,如java.base模块:

module java.base{
 exports java.io;
 exports java.lang;
 exports java.lang.annotation;
 exports java.lang.invoke;
 exports java.lang.module;
 exports java.lang.ref;
 exports java.lang.reflect;
 exports java.lang.math;
 exports java.lang.net;
 //...
}

所有的应用都会默认依赖 java.base,就像以前我们不用显式的 "import java.lang.*;" 一样。

这里验证了前面helloworld中,为什么反编译模块文件之后会多了一个:"requires java.base;"。

下面的 com.foo.app 模块,不需要显式地引入java.base:

如果此时com.foo.bar 增加了 com.foo.baz 模块的引用。

那么,我们知道 com.foo.bar 也隐式 引入了 java.base。

同样的道理,com.foo.baz 模块也隐式引用了 java.base:

可靠的配置

继续深入下去,我们知道 java.sql 引用了其他大量的api,那么下图就不难理解了。

目前的模块结构,称为可读的模块,提供了可靠的配置。

如果引用了不存在的module,和jar一样,你同样会触发 xx not found.

编译时:

运行时:

如果引用的模块没有导出某个类,那么是不可访问的,这称为强封装。

比如 com.foo.bar 模块中有一个内部类BetaImpl:

比如 com.foo.bar 模块中有一个内部类BetaImpl:

那么在 com.foo.bar 模块的主动引用模块 com.foo.app 中如下使用 BeatImpl:

在编译时,会触发异常:

就是说:BetaImpl不可访问,因为包 com.foo.bar.beta.internal 包没有被导出。

同样,即便使用导出版本编辑成功,而运行时引用了未导出版本模块:

查看內建的模块

$ jmod list $JAVA_HOME/jmods/java.base.jmod
classes/module-info.class
classes/apple/security/AppleProvider$1.class
...
classes/java/lang/Object.class
...
bin/java
bin/keytool
...
conf/security/java.policy
...

查看更多内建模块:

$ java --list-modules
java.activation@9
java.base@9
java.compiler@9
java.corba@9
java.datatransfer@9
java.desktop@9
//...节省篇幅略

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表