参考网站:The State of the Module System,Java9模块系统的说明(翻译),Java9 中的 Module, ModulePath 和 ClassPath,Java 9 揭秘(4. 模块依赖)

  • 每个java project中的根目录下都有一个module-info.java
  • 模块名不可重复,因此建议采用类似包名的结构。
  • <>中的名字需要是全限定名,不管是包名、类名或是接口名。
    此外,在exports<package name>中,java.langjava.lang.annotation是不同的包,需要分开写,只写java.lang则只能公开该包下的类,而不会公开java.lang.annotation下的类。

使用示例(以及Maven整合java9):https://www.jianshu.com/p/66c26dd3237f


requires public

module <module name> {requires <module>;requires public <module>;exports <module>;
}
  • A模块下可包括packagea、packageb、packagec包,如果要向其他模块公开packagea包,则需要用exports packagea
  • B模块如果要使用A模块,则需要使用requires A(同时还需要将该组件加入到项目->buildpath->Modulepath)
  • 接上,C模块即使引用了B模块requires B,也无法使用A模块中的内容。如果希望让C模块可以通过引用模块B,从而间接引用A模块,则需要在B模块中声明requires public A,这称为隐式可读性(implied readability)。

requires static

module <module name> {requires static <optional-package>;
}

模块系统在编译时以及运行时验证模块的依赖关系。 有时希望在编译时模块依赖性是必需的,但在运行时是可选的。

你在开发一个库时,如果一个特定的模块在运行时可执行更好的库。否则,它将回到另一个模块,使其执行不到最佳的库。但是,库是根据可选模块进行编译的,如果可选模块不可用,则确保不依赖于可选模块的代码执行。

另一个例子是导出注解包的模块。 Java运行时已经忽略不存在的注解类型。 如果程序中使用的注释在运行时不存在,则注解将被忽略。 模块依赖关系在启动时验证,如果模块丢失,应用程序将无法启动。 因此,必须将含有注解包的模块的模块依赖性声明为可选。

以下模块声明包含对com.jdojo.annotation模块的可选依赖关系:

module com.jdojo.claim {requires static com.jdojo.annotation;
}

允许在require语句中同时使用transitive 和static 修饰符:

module com.jdojo.claim {requires transitive static com.jdojo.annotation;
}

如果transitive 和static 修饰符一起使用,则可以按任何顺序使用。 以下声明具有与之前相同的语义:

module com.jdojo.claim {requires static transitive com.jdojo.annotation;
}

exports & exports to

module A {exports com.packageAexports com.packageB to B;exports com.packageC to C,D,E;
}
  • export语句用于将包导出到所有其他模块或某些命名模块。
  • 导出的包中的所有公共类型都可以在编译时和运行时访问。
  • 在运行时,可以使用反射来访问公共类型的公共成员;但公共类型的非公开成员也无法使用反射,即使在这些成员上使用了setAccessible(true)方法。
  • 指定导出的com.packageB仅对B模块可见.
  • 指定导出的com.packageC仅对C,D,E这三个模块可见

open & opens

要反射公共字段,需要exports导出包,这是允许的最小可访问性。要反射非公共字段,必须打开opens该包,这是允许的最大可访问性。

open module com.jdojo.model {// Module statements go here
}
  • 在这里,com.jdojo.model模块是一个开放模块。 其他模块可以在本模块中的所有软件包上对所有类型使用深层反射(详见Java 9 揭秘(4. 模块依赖)——四——3. 使用深度反射)(简单来说就是可以通过反射访问非公共字段)。
  • 可以在开放模块中声明 exports, requires, uses, 和provides语句。
  • 但不能在打开的模块中再声明opens语句。 opens语句用于打开特定的包以进行深层反射。 因为开放模块打开所有的软件包进行深层反射,所以在开放模块中不允许再使用open语句。

打开一个包意味着允许其他模块对该包中的类型使用深层反射。 可以打开一个包指定给所有其他模块或特定的模块列表。
打开一个包到所有其他模块的打开语句的语法如下:

opens <package>;

这里,可用于深入反射所有其他模块。 也可以使用限定的open语句打开包到特定模块:

opens <package> to <module1>, <module2>...;

在这里,仅用于深层反射到,等。以下是在模块声明中使用opens语句的示例:

module com.jdojo.model {// Export the com.jdojo.util package to all modulesexports com.jdojo.util;// Open the com.jdojo.util package to all modulesopens com.jdojo.util;// Open the com.jdojo.model.policy package only to the hibernate.core moduleopens com.jdojo.model.policy to hibernate.core;
}
  • com.jdojo.model模块导出com.jdojo.util包,这意味着所有公共类型及其公共成员在编译时可以访问,并在运行时进行反射。
  • 第二个语句在运行时打开相同的包进行深度反射。 总而言之,com.jdojo.util包的所有公共类型及其公共成员都可以在编译时访问,并且该包允许在运行时深层反射。
  • 第三个语句仅将com.jdojo.model.policy包打包到hibernate.core模块进行深层反射,这意味着其他模块在编译时不能访问此包的任何类型,而hibernate.core模块可以访问所有类型及其成员在运行时进行深度反射。

uses & provides to

module com.demo.consumer {requires com.example.data;uses com.example.data.SortService;
}
  • uses用于声明需要的接口,这样就可以使用ServiceLoader.load方法去加载依赖中的service provider
  • uses [interface]当前模块就会发现它,使java.util.ServiceLoader类进行加载。必须是本模块中的,不能是其他模块中的。其实现类可以由其他模块提供。
module service.sort.bubble {requires service.sort;provides com.example.data.SortService with sort.impl.bubble.BubbleSort;
}
  • provides [interface] with [implement]声明了是SortService的服务提供方,好让模块系统知道这个模块提供了该接口的实现。
  • 注意这里不需要exports这个实现类,即服务提供模块可以不用exports服务实现。

规范 & 兼容和迁移

java1.8及以前的项目使用java9之后的模块化jar包:

  1. 只需要使用Classpath即可。
  • Classpath中的的Jar包,无论是否模块化都会被当作传统Jar包处理。
  1. 主程序放在classpath中。平台内建模组(jmod)放在modulepath中。
  • 所有Classpath下的内容在Java9中会变成一个未命名模块(Unnamed Module)
  • 未命名模块会导出它的所有包。

java9之后,创建一个模块化的项目,但是依赖的Jar包还没有模块化:

  1. 将非模块化jar包放入modulepath中。
  • 一个不包含module-info.class的传统Jar包,如果放到了ModulePath下,就变成了一个自动模块(Automatic Module)
  • 自动模块默认的依赖于所有Modulepath中的模块,可以访问所有模块中导出的Package。默认导出此模块中的所有Package。
  • 自动模块被授予对其它所有自动模块的隐式可读性。(即自动模块中对其他自动模块的依赖都是requires public [com.automiaticModule],显示模块不需要考虑各个自动模块之间的相互依赖问题)
  • 不同自动模块中的package不能重复。(如果modulepath中两个以上的非模块化jar包包含相同的package,只有一个jar包可以成为自动模块)。

小结

  • Modulepath中的Jar包或Jmod文件被当作Module来处理,而Classpath中的的Jar包,无论是否模块化都会被当作传统Jar包处理。

  • modulepath中模块化jar包为显示模块,非模块化(没有模块声明)的jar包为自动模块;classpath中的jar包被视为未命名模块

    未命名模块

  • Unnamed Module是一个特殊的,自动生成的Module,所有Classpath下的内容在 Java9中都是挂在Unnamed Module(未命名模块)名下的。对于同一个ClassLoader,只有一个 未命名模块。

  • Unnamed Module会导出它的所有包。

  • Unnamed Module可以读取其他任意模块。

  • 显示模块不能读取未命名模块。(这个限制是有意为之的。因为允许命名模块依赖类路径中的任意内容是不可能做到可靠的配置的)

  • 如果一个包被定义在了命名模块和未命名模块中,那么未命名模块中的包会被忽略。(假设com.xxxPackage包是com.moduleA模块的导出包,包里面有Alpha.class类,同时如果一个类路径下的JAR文件包含com/xxxPackage/Alpha.class类,则该文件将永远不会被加载。)

    自动模块

  • 一个不包含module-info.class的传统Jar包,如果放到了ModulePath下,就变成了一个自动模块(Automatic Module)

  • 自动模块默认的依赖于所有Modulepath中的模块,可以访问所有模块中导出的Package。默认导出此模块中的所有Package。

  • 自动模块被授予对其它所有自动模块隐式可读性*(*见总结1)。(自动模块之间)

  • 如果 Jar 包在MetaInfo文件中定义了Automatic-Module-Name,则使用这个值作为模块的名称;如果没有定义,那么使用 Jar 包的文件名去掉扩展名的那部分作为模块名,其中包含的“-”要替换成“.”,因为模块名不允许包含“-”字符。

  • 自动模块可以读取未命名模块。显示模块不能读取未命名模块。(例如,显示模块com.explicitModule中的代码引用了自动模块com.automaticModule中的公共类型,并且自动模块com.automaticModule的方法签名引用了还在Classpath路径中的JAR文件中的类型,那么显示模块com.explicitModule中的代码将无法访问这些类型,因为显示模块不能依赖未命名模块。临时的解决方案为:将显示模块com.explicitModule改为自动模块,直到classpath中的jar包被模块化,并移入modulepath中)

Java9 module特性 初识相关推荐

  1. Java9 新特性 详解

    目录 Java9 新特性 详解 1.Java9新特性之---目录结构 2.Java9新特性之---JShell工具 3.Java9新特性之---模块化 4.Java9新特性之---多版本兼容Jar包 ...

  2. JAVA9 新特性 完整使用

    JAVA9 新特性 完整使用 一.介绍(java9新特性) 1.Oracle JDK9 Documentation(java9新特性) 2.官方提供新特性列表(java9新特性) 3.JDK和JRE ...

  3. 【小家java】java9新特性(简述十大新特性) 褒贬不一

    相关阅读 [小家java]java5新特性(简述十大新特性) 重要一跃 [小家java]java6新特性(简述十大新特性) 鸡肋升级 [小家java]java7新特性(简述八大新特性) 不温不火 [小 ...

  4. Java9新特性系列(模块化系统: Jigsaw-Modularity)

    模块化的前时代 Ant时代 相信大家对Ant都不陌生,Ant是任务型的,定义了一系列的任务dir/compile/jar等等,缺点是操作文件 Maven时代 Maven/Gradle相对于Ant,增加 ...

  5. java9新特性--jShell--命令语法改进:try语和接口的私有方法--String存储结构变更--集合工厂方法--模块化系统--InputStream 加强--增强的 Stream API

    目录 Java 9 的新特性 JDK 和 JRE 目录结构的改变 模块化系统: Jigsaw -> Modularity 实现目标 模块 结构 jShell命令 产生背景 设计理念 实现目标 j ...

  6. C++20四大之一:module特性详解

    前言 C++20最大的特性是什么? --最大的特性是迄今为止没有哪一款编译器完全实现了所有特性. C++20标准早已封版,各大编译器也都已支持了C++20中的多数特性,但迄今为止(2021.7),尚未 ...

  7. 技术干货 | C++20 四大特性之一:Module 特性详解

    导读:C++20 标准早已封版,各大编译器也都已支持了 C++20 中的多数特性,但迄今为止(2021.7),尚未有哪一款编译器完整支持 C++20 中的所有特性.本文仅介绍 C++20 四大特性当中 ...

  8. 即将改变软件开发的5个Java9新特性

    预计发布的Java 9中,最令人兴奋的特性是什么? 有关Java9的消息最近显得有些沉寂,不要被它迷惑了.JDK开发者正在努力朝着下一个版本迈进,计划2015年12月前完成所有功能开发.之后,它会经历 ...

  9. java9新特性-4-模块化系统: Jigsaw与Modularity

    1.官方Feature 200: The Modular JDK 201: Modular Source Code 220: Modular Run-Time Images 260: Encapsul ...

最新文章

  1. 程序员初试和复试_程序员的软微mem经验贴
  2. 如何配置和部署安全的.NET三层应用
  3. 一劳永逸的搞定 flex 布局
  4. 体系化认识RPC--转
  5. 【Greenplum代码】记录一次不了解GP数据库编号函数使用方法导致的问题(1次疏忽 + 1次不必要 = 2次弯路)
  6. PHP索引数组+unset使用不当导致的问题
  7. web登录界面设计_出色的Web界面设计的7条规则
  8. Android之BaseQuickAdapter(3.0.4版本)给子view添加点击事件(helper.addOnClickListener(view))的函数没了
  9. Java并发编程实战~Thread-Per-Message模式
  10. 【转载】Apache Ranger剖析:Hadoop生态圈的安全管家
  11. 2018北理复试机试题
  12. Carthage 安装与使用
  13. Altium Designer元件库常见获取方法
  14. php.ini gd_php安装gd扩展
  15. python爬大学生就业信息报告_Python语言爬虫——Python 岗位分析报告
  16. 活性氧Propiconazole-d3 (nitrate),CAS No. 2699607-26-4
  17. 汽车零部件-线控底盘
  18. 地理信息科学与计算机科学与技术专业,浙江大学地理信息科学专业怎么样
  19. 汽车后市场O2O的掘金点在供应链金融
  20. 看这里!你的手机号关联了多少互联网账号?一证通查→

热门文章

  1. ZYNQ PL操作DDR内存读写测试
  2. 移动互联网时代的大数据挖掘和精准营销
  3. 计算机组成原理第二章练习题(答案详解)
  4. 出国留学海外电汇流程
  5. 易语言-POST上传数据
  6. iic模块PCF8574驱动1602学习记载
  7. mac下使用夜神模拟器调试
  8. 老胡的惊天大阴谋,彻底伤害了公司小姑娘...
  9. 逆势:衰退的开发者信心和不断示好的开发环境
  10. 开卷有益:《一分钟经理人》之一分钟目标