Java 9的最大功能之一将是Project Jigsaw定义的模块系统。在JavaOne 2015上阅读Project Jigsaw: Under the Hood的幻灯片时,我注意到以下源代码:
// src/java.sql/module-info.java
module java.sql {
exports java.sql;
exports javax.sql;
exports javax.transaction.xa;
}
有趣的是,该文件以.java
结尾,似乎使用了两个新关键字:module
和exports
。 Java 9中将引入哪些其他关键字?如何处理向后兼容性(即名为module
)的函数或变量?
答案 0 :(得分:65)
在Java 9中为模块声明添加的关键字总结如下 Java Language Specification, Java SE 9 Edition中的§3.9:
另外十个字符序列是受限制的关键字:
open
,module
,requires
,transitive
,exports
,opens
,to
,uses
,provides
和with
。这些字符序列被标记为 关键字仅在ModuleDeclaration中显示为终端的位置 和ModuleDirective制作(第7.7节)。它们被标记为 其他地方的标识符,与编写的程序兼容 在Java SE 9之前。有一个例外:紧靠右侧 在ModuleDirective制作中需要字符序列, 字符序列传递被标记为关键字,除非它 后跟一个分隔符,在这种情况下它被标记为一个 标识符
如果您目前有一个名为module
的方法,或任何其他方法
这里列出的关键词,它将继续编译。
(view
和permits
是早期Jigsaw原型中的关键字,但是
他们很久以前就被简化了。)
答案 1 :(得分:5)
这可能不是一个完整的清单,根据我的知识,这些都没有最终确定,但我发现了一些。
我们还有module
,exports
,provides
,uses
,with
,to
和requires
;解释here:
模块系统可以通过扫描模块工件中的类文件来识别ServiceLoader :: load方法的调用来识别服务的使用,但这既缓慢又不可靠。模块使用特定服务是该模块定义的一个基本方面,因此为了效率和清晰度,我们在模块的声明中用uses子句表示:
module java.sql { requires public java.logging; requires public java.xml; exports java.sql; exports javax.sql; exports javax.transaction.xa; uses java.sql.Driver; }
模块系统可以通过扫描META-INF /服务资源条目的模块工件来识别服务提供者,就像ServiceLoader类今天所做的那样。但是,模块提供特定服务的实现同样是基础,因此我们在模块的声明中用provide子句表示:
module com.mysql.jdbc { requires java.sql; requires org.slf4j; exports com.mysql.jdbc; provides java.sql.Driver with com.mysql.jdbc.Driver; }
...
module java.base { ... exports sun.reflect to java.corba, java.logging, java.sql, java.sql.rowset, jdk.scripting.nashorn; }
view
和permits
:
在大型软件系统中,定义同一模块的多个视图通常很有用。一个视图可以声明为任何其他模块的一般用途,而另一个视图提供对内部接口的访问,这些接口仅供一组紧密相关的模块使用。
例如,对于JNDI,我们希望com.sun.jndi.toolkit.url仅对cosnaming和kerberos模块可见,如模块声明中所指定。
view jdk.jndi.internal { exports com.sun.jndi.toolkit.url.*; exports sun.net.dns.*; permits jdk.cosnaming; permits jdk.kerberos;
}
通过这种方式,我们可以更灵活地定义模块边界。
我也听说过optional
。
答案 2 :(得分:0)
*
module mainModule @ 2.0 {
requires A @ >= 3.0 ; // Use version 3 or above
//scope:compilation,execution,reflection
requires B for compilation optional execution;
requires optional service S1;
requires static E; // need at compile time but optional at runtime
// let mmm requires mainModule then S2 will automatically be there for mmm
requires transitive S2;
provides MI @ 2.0;
provides service MS with C; // provide service with impelemented class C
exports pack;
exports pack.abc to D; //qulified export
permits MF;
class MMain;
/*
syntax for creating view
view ModuleName {
{ProvidesDir|ExportsDir|PermitsDir|EntrypointDir}
}
*/
view N {
provides service NS with AD;
exports MA;
permits MB;
class Main;
}
}
* 检查一下可能对您有帮助。
答案 3 :(得分:-1)
模块是一个 new 关键字,用于定义软件包之间的相互依赖关系。 为什么我们需要模块? 因为早些时候
如果类加载器没有获得类,则必须查看很多区域并加载大量相关文件,如果找不到类,则会在运行时抛出NoClassDefFoundErrors。 / p>
因此,出于上述所有原因,我们需要一种机制,让JVM在运行时知道这一点。要实现模块,您需要定义module-info.java
。 in that package
module com.exporter{
exports com.a;
provides com.b.M;
with com.b.MImpl; }
在其他一些包中,
module com.consume {
requires com.a;
}
使用的其他属性是“导出”和“需要”,用于建立互连(仅限传递依赖),“提供”和“ with ”用于公开界面和提及实现。 所以它可能是一个强大的封装,这就是为什么java 9更倾向于更好的面向对象特性。
答案 4 :(得分:-4)
对于问题的向后兼容性部分。
我认为JAVA9 /项目拼图是Java技术的范例转换。 因此java9不会向后兼容,但您可以使用同一库的模块化版本轻松转换非模块化依赖项。 “没有痛苦,没有收获”的概念将在这里发挥作用。 每个人都必须升级/转换以利用新的模块化Java。 IDE开发人员,插件开发人员,构建系统以及当然不熟悉Java系统的人员。
JAVA9倡导清洁依赖。 它还提供了一种通过私有模块保护代码的全新方式。 甚至反射也无法访问库/ API所有者未公开的模块。
使用非模块化LIB / API有两种方法。
第二种方法是一个非常干净的模块依赖层次结构。