• [Open JDK-11 源码解析系列]-3-JDK9到JDK11的新增的语法变化


    3-JDK9到JDK11的语法变化

    3.1 Java SE 9 的 Java 语言更改

    3.1.1 模块

    在此版本中引入Java 平台模块系统。
    Java 平台模块系统引入了一种新的 Java 编程组件,即模块,它是一个命名的、自描述的代码和数据的集合。它的代码被组织成一组包含类型的包,即Java类和接口;它的数据包括资源和其他种类的静态信息。模块可以导出或封装包,它们显式地表达对其他模块的依赖。

    JDK的模块化如下图:
    在这里插入图片描述

    也可以参考链接:openjdk9模块

    • 标准 Java SE 模块为橙色;非 SE 模块为蓝色。
    • 如果一个模块依赖于另一个模块,并且它赋予该模块隐含的可读性,那么从第一个模块到第二个模块的边缘是可靠的;否则,边缘为虚线。

    定义模块

    为了提供可靠的配置和强大的封装,开发人员可以使用并且现有工具链可以支持,我们将模块视为一种基本的新型 Java 程序组件。模块是一个命名的、自描述的代码和数据集合。它的代码被组织成一组包含类型的包, 即Java 类和接口;它的数据包括资源和其他种类的静态信息。

    模块声明

    模块的自我描述在其模块声明中表达,这是 Java 编程语言的一种新结构。最简单的模块声明仅指定其模块的名称:

    module com.foo.bar { }
    
    • 1

    可以添加一个或多个requires子句来声明该模块在编译时和运行时按名称依赖于其他一些模块

    module com.foo.bar {
        requires org.baz.qux;
    }
    
    • 1
    • 2
    • 3

    最后,exports可以添加子句来声明模块使特定包中的所有公共类型可供其他模块使用:

    module com.foo.bar {
        requires org.baz.qux;
        exports com.foo.bar.alpha;
        exports com.foo.bar.beta;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    如果模块的声明不包含exports子句,那么它根本不会将任何类型导出到任何其他模块。

    按照惯例,模块声明的源代码放置在一个名为module-info.java模块源文件层次结构根目录的文件中。com.foo.bar模块的源文件,例如,可能包括:

    module-info.java
    com/foo/bar/alpha/AlphaFactory.java
    com/foo/bar/alpha/Alpha.java
    
    • 1
    • 2
    • 3

    按照惯例,模块声明被编译成一个名为 的文件 module-info.class,类似地放置在类文件输出目录中。

    模块名称,如包名称,不得冲突。命名模块的推荐方法是使用长期以来被推荐用于命名包的反向域名模式。因此,模块的名称通常是其导出包名称的前缀,但这种关系不是强制性的。

    模块英文文档介绍

    3.1.2 更简洁的 try-with-resources 语句

    如果您已经将资源作为变量final或有效final变量,则可以在try-with-resources语句中使用该变量而无需声明新变量。“有效最终”变量是其值在初始化后从未更改过的变量 。

    例如,您声明了这两个资源:

            // A final resource
            final Resource resource1 = new Resource("resource1");
            // An effectively final resource
            Resource resource2 = new Resource("resource2");
            //在 Java SE 7 或 8 中,将声明新变量r1和r2,如下所示:
             try (Resource r1 = resource1;
                 Resource r2 = resource2) {
                 //...
            }
            // Java SE 9 中,不需要声明r1and r2:
           try (Resource r1 = resource1;
                 Resource r2 = resource2) {
                //...
            }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    3.1.3 下划线字符不是合法名称

    如果您使用下划线字符(“_”)作为标识符,您的源代码将无法再编译。

    3.1.4 支持私有接口方法

    支持私有接口方法。这种支持允许接口的非抽象方法在它们之间共享代码。

    3.2 Java SE 10 的 Java 语言更改

    3.2.1 局部变量类型推断

    在此版本中引入。Local-Variable Type Inference 将类型推断扩展到使用初始化程序的局部变量声明

    以下示例中显示的代码似乎是多余的,并且使代码更难阅读。

    URL url = new URL("http://www.elastic.link"); 
    URLConnection conn = url.openConnection(); 
    Reader reader = new BufferedReader( 
        new InputStreamReader(conn.getInputStream()));
    
    • 1
    • 2
    • 3
    • 4

    一个名为的新标识符var现在可用于具有非空初始值设定项的局部变量。使用这个标识符,变量的类型是从上下文中推断出来的。上一个示例中的代码可以重写,如下例所示:

    var url = new URL("http://www.elastic.link"); 
    var conn = url.openConnection(); 
    var reader = new BufferedReader( 
        new InputStreamReader(conn.getInputStream()));
    
    • 1
    • 2
    • 3
    • 4

    var是保留的类型名称,而不是关键字,这意味着var用作变量、方法或包名称的现有代码不受影响。但是,var用作类或接口名称的代码会受到影响,需要重命名类或接口。

    var可用于以下类型的变量:

    • 带有初始化器的局部变量声明
    • 增强的 for 循环索引
    • 在传统 for 循环中声明的索引变量
    • Try-with-resources 变量

    以下代码显示了使用示例var:

    var list = new ArrayList<String>(); // 推断 ArrayList<String> 
    var stream = list.stream(); // 推断 Stream<String> 
    
    var path = Paths.get(fileName); // 推断路径
    var bytes = Files.readAllBytes(path); // 推断 bytes[] 
    
    for (var counter=0; counter<10; counter++) {...} // 推断 int 
    
    try (var input = 
         new FileInputStream ("validation.txt")) {...} //文件输入流
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    相关英文文档可以参考局部类型推断

    3.3 Java SE 11 的 Java 语言更改

    增强类型推断

    var在 JDK 11 及更高版本中,您可以使用标识符 声明隐式类型 lambda 表达式的每个形式参数:

    隐式类型 lambda 表达式的形式参数声明:其形式参数具有推断类型的 lambda 表达式是隐式类型的:

    BiFunction<Integer, Integer, Integer> = (a, b) -> a + b;
    
    • 1

    var在 JDK 11 及更高版本中,您可以使用标识符 声明隐式类型 lambda 表达式的每个形式参数:

    (var a, var b) -> a + b;
    
    • 1

    因此,隐式类型 lambda 表达式中形式参数声明的语法与局部变量声明的语法一致;将var标识符应用于隐式类型 lambda 表达式中的每个形式参数与根本不使用具有相同的效果var。

    您不能var在隐式类型的 lambda 表达式中混合推断形式参数和 - 声明的形式参数,也不能var在显式类型的 lambda 表达式中混合 - 声明的形式参数和清单类型。不允许使用以下示例:

    (var x, y) -> x.process(y)      // Cannot mix var and inferred formal parameters
                                    // in implicitly typed lambda expressions
    (var x, int y) -> x.process(y)  // Cannot mix var and manifest types
                                    // in explicitly typed lambda expressions
    
    • 1
    • 2
    • 3
    • 4

    查看原文,技术咨询支持,可以扫描微信公众号进行回复咨询
    在这里插入图片描述

  • 相关阅读:
    google搜索技巧——程序员推荐
    (2022版)一套教程搞定k8s安装到实战 | K8s集群安装(二进制)
    TCP 和UDP 的详细介绍
    【经历】在职8个月->丰富且珍贵
    docker简洁版
    Java—类加载机制
    问题解决——SSH时出现WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!(转)
    嵌入式学习——C语言基础——day8
    计算机毕设(附源码)JAVA-SSM基于专家系统房产营销智能推荐系统
    OpenCV从入门到入坟
  • 原文地址:https://blog.csdn.net/songjunyan/article/details/125011966