【问题标题】:New Keywords in Java 9Java 9 中的新关键字
【发布时间】:2016-03-31 00:37:37
【问题描述】:

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 结尾,并且似乎使用了两个新关键字:moduleexports。 Java 9 中还会引入哪些其他关键字?如何处理向后兼容性(即名为 module 的函数或变量)?

【问题讨论】:

  • 我想在某个时候我们也会得到refany
  • @PaulBoddington 对于 any 关键字肯定不在 Java 9 中。那就是瓦尔哈拉,即。 10 或更高版本。
  • “将如何处理向后兼容性”,大概和往常一样:你必须用旧的源代码版本编译受影响的文件

标签: java syntax java-9 java-platform-module-system


【解决方案1】:

Java 9 中为模块声明添加的关键字总结在 Java Language Specification, Java SE 9 Edition 的§3.9:

另外十个字符序列是受限关键字:openmodule, requires, transitive, exports, opens, to, uses, provideswith。这些字符序列被标记为 仅在 ModuleDeclaration 中作为终端出现的关键字 和 ModuleDirective 产品(§7.7)。它们被标记为 其他地方的标识符,以与编写的程序兼容 在 Java SE 9 之前。有一个例外:紧靠右边 ModuleDirective 产品中需要的字符序列, 字符序列传递被标记为关键字,除非它 后跟一个分隔符,在这种情况下,它被标记为 标识符。

如果您目前有一个名为 module 的方法,或任何其他 此处列出的关键字,它将继续编译。

(viewpermits 是早期 Jigsaw 原型中的关键字,但 它们在很久以前就被简化了。)

【讨论】:

  • 您有关于viewpermits 的任何信息,仅用于历史/文档资料吗?
  • 列表中似乎缺少传递性?
  • 限制关键字是一个很棒的主意。我希望它们能被更频繁地使用。
  • openopens 也不见了。
  • "从第 9 版开始,'_' 是关键字,不能用作标识符"这是一项重大更改。
【解决方案2】:

这可能不是一个完整的列表,据我所知,这些都没有最终确定,但我找到了一些。

我们还有moduleexportsprovidesuseswithtorequires;解释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 类一样。然而,模块提供特定服务的实现同样重要,因此我们在模块的声明中用提供子句表示:

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;
}

还有viewpermits

在大型软件系统中,定义同一模块的多个视图通常很有用。一个视图可以声明为供任何其他模块通用使用,而另一个视图提供对内部接口的访问,仅供一组选择的密切相关的模块使用。

例如,对于 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

【讨论】:

  • 我知道Optional<T>这个类,但他们真的在考虑把它作为关键字吗?那个有 JEP 吗?
  • 更不用说...withto 是非常常用的变量名。我希望关键字仅在 module 定义中相关使用!
  • 希望如此!我找不到好的官方资源,但 Jigsaw Project 文档似乎表明它们是“修饰符”而不是关键字......希望在脱离module 的上下文使用时不会保留它们。
【解决方案3】:

*

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;

     }
}

* 看看它可能对你有帮助。

【讨论】:

    【解决方案4】:

    module是一个new关键字,用于定义包之间的相互依赖关系。 为什么我们需要模块? 因为更早

    1. 封装并不完美。在反射和类似技术的帮助下,我们甚至可以访问私有字段。

    2. 所有 jar 中的所有类都可以公开访问。

    3. 如果 Classloader 没有得到类,它必须查看很多区域并加载很多相关文件,即使在此之后如果找不到 Class,它也会在运行时抛出 NoClassDefFoundErrors。

      因此,出于上述所有原因,我们需要一种机制,让 JVM 在运行时知道这一点。对于实现模块,您需要定义module-info.javain that package

          module com.exporter{
      
           exports com.a;
           provides com.b.M;
            with com.b.MImpl; }
      

    在其他一些包中,

    module com.consume {
        requires com.a;
    }
    

    使用的其他属性是“exports”和“requires”用于建立相互依赖(仅限传递依赖),“provides”和"with" 用于公开接口和提及实现。 所以它可能是一个强大的封装,这就是为什么 java 9 更倾向于更好的面向对象特性。

    【讨论】:

      【解决方案5】:

      关于问题的向后兼容性部分。

      我认为 JAVA9/project jigsaw 是 Java 技术的一种范式转变。 这样java9就不会向后兼容,但是你可以很容易地用同一个库的模块化版本转换你的非模块化依赖。 “No-Pain , No-Gain”的概念将在这里发挥作用。 每个人都必须升级/改造以利用新的模块化 java。 IDE 开发人员、插件开发人员、构建系统,当然还有底层 Java 开发人员需要了解新的 Java 系统。

      JAVA9 提倡干净的依赖。 它还提供了一种全新的方式来通过私有模块保护您的代码。 甚至反射也无法访问库/API 所有者未公开的模块。

      有两种方法可以使用非模块化 LIB/API。

      1. 自上而下的方法
      2. 自下而上的方法(实施起来很麻烦)

      第二种方法使模块依赖层次结构非常干净。

      【讨论】:

      • “这样java9就不会向后兼容……”不正确。如果您的程序没有定义任何模块,它将完全像在 Java 8 中那样工作。
      • 除非您访问内部 api 或尝试对模块中的任何内容使用反射,否则您的程序将正常工作。
      猜你喜欢
      • 2016-04-21
      • 1970-01-01
      • 2015-12-24
      • 2014-04-10
      • 2020-11-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-12-31
      相关资源
      最近更新 更多