Java模块系统新特性快速上手指南


Java模块系统新特性快速上手指南文章插图
Java平台模块系统
0.导引Java发展的越来越无所不能了 , 从Java 9+开始而引入的平台模块系统 , 就是一个很大的新特性 , 使组织代码变得更容易 , 也更易于功能解耦化和微型化 。 本文是一个使用Java模块的简短快速上手指南 。
在Java 9之前 , Java的顶级代码组织元素一直是包 。 从Java 9开始变了:在包package的上面是模块module 。 模块将相关的包收集聚合在一起 。
Java平台模块系统(JPMS , Java Platform Module System)是一种代码级结构 , 其不会改变将Java打包到JAR文件中的事实 。 本质上讲 , 所有内容仍然打包在JAR文件中 。 模块系统通过结合 module-info.java文件 , 添加了jar可以使用的新的高级描述符 。
大型应用程序和组织机构 , 可以利用模块化来更好地组织代码 。 其实现在每个人都在使用着模块 , 因为JDK及其类现在已经模块化了 。
1.为什么Java需要模块JPMS是Jigsaw工程的成果 , 该工程的目标如下:

  • l 使开发人员更容易组织大型应用程序和库;
  • l 改进平台和JDK本身的结构和安全性;
  • l 提高应用程序性能;
  • l 对于较小的设备 , 更好地处理平台的分解面 。
值得注意的是 , JPMS是一个SE(标准版)特性 , 因此会从头影响Java的各个方面 。 尽管如此 , 这种结构改变后的设计 , 当在从Java 8迁移到Java 9时 , 最大程度的允许功能代码无需修改即可运行 。 这里有一些例外 , 我们将在稍后的概述中进行说明 。
模块背后的主要思想是允许相关包的集合对模块是可见的 , 而对模块的外部使用者隐藏一些要素 。 换句话说 , 模块是允许另一种级别的封装 。
2.类路径和模块路径到目前为止 , 在Java中 , 类路径一直是运行着的程序的可用内容的底线 。 尽管类路径服务于此目的 , 并且很容易理解 , 但它最终将是一个大的、无差异的桶 , 所有依赖项都被放置在其中 。
模块路径在类路径之上添加了一个级别 。 它充当包的容器 , 并决定哪些包对应用程序可用 。
3.JDK中的模块JDK本身现在是由模块组成的 。 让我们从JPMS的细节开始 。
如果您的系统上有JDK , 那么您也有源代码 。 如果您不熟悉JDK以及如何获得它 , 请参阅@牛旦IT课堂的这篇文章:JDK 、JRE 与JVM之间的关系及区别。
在JDK安装目录中有一个/lib目录 。 在该目录中有一个src.zip文件 。 将其解压缩到/src目录中 。
查看/src目录 , 并导航到/java.base目录 。 在那里您将找到module-info.java文件 , 然后打开它 。
【Java模块系统新特性快速上手指南】在头部的Javadoc注释之后 , 您会发现一个命名为module java.base的部分 , 其随后有一系列exports行 。 这里我们不详细讨论格式 , 因为它相当深奥 。 详情请点击这里的连接()——有机会我再详解之 。
您可以看到许多熟悉的Java包 , 比如java.io , 是从java.base模块导出的 。 这是集合或汇聚相关包的模块本质 。
exports的另一面是requires指令 。 这允许被定义的模块被引入(需要)到某个模块 。
在对模块运行Java编译器时 , 可以类似于类路径的方式指定模块路径 。 这样就可以解决依赖问题 。
4.创建模块化Java项目让我们来看看模块化Java项目是如何构建的 。 我打算创建一个有两个模块的小程序 , 一个提供依赖项 , 另一个使用依赖项并导出一个可执行的主类 。
在文件系统中某地方创建一个新目录(模块名),叫它/com.inewday.mod1 。 按照约定 , Java模块位于与模块同名的目录中 。
Java模块系统新特性快速上手指南文章插图
现在 , 在这个目录中 , 创建一个module-info.java文件 。 在其中添加清单1中的内容 。
清单 1: com.inewday.mod1/module-info.java
module com.inewday.mod1 {exports com.inewday.package1;}请注意 , 模块和它导出的包是不同的名称 。 此处我定义了导出包的模块 。
现在在这个路径上创建一个文件 , 在目录中包含module-info.java文件:/com.inewday.mod1/com/inewday/package1 。 将文件命名为Name.java 。 将清单2的内容写入其中 。
清单2 Name.java
package com.inewday.package1; public class Name {public String getIt() {return "Java Module World";}}清单2将成为我们所依赖的类、包和模块 。
现在我来创建另一个与/com.inewday.mod1平行的目录 , 并叫做/com.inewday.mod2 。 在这个目录中 , 我来创建一个module-info.java模块定义 , 它导入我已经创建的模块 , 如清单3所示 。