Java 11新特性概述

    xiaoxiao2022-07-03  111

    转自:http://www.52im.net/article-340-1.html

    概述

     

    美国时间2018年09 月 25 日,Oralce 正式发布了 Java 11,这是 Java 8 发布以后支持的首个长期版本

     

    为什么说是长期版本,看下面的官方发布的支持路线图表:

     

    可以看出 Java 8 扩展支持到 2025 年,而 Java 11 扩展支持到 2026 年。

     

    现在大部分都在用 Java 8,Java 9 和 10 目前很少有人在用,至少我没有发现有公司在生产环境应用的,那就是找死。现在 Java 11 长期支持,也已经包含了 9 和 10 的全部功能,9 和 10 自然就活到头了。。

     

    那么我们来看下 从 Java 9 - 11 都有哪些重要的新特性呢?

    1、本地变量类型推断

    这个博主已经写过一篇文章,详细的介绍了 Java 10 带来的这个新特性。

     

    什么是局部变量类型推断?

    var javastack = "javastack"; System.out.println(javastack);

     

    大家看出来了,局部变量类型推断就是左边的类型直接使用 var 定义,而不用写具体的类型,编译器能根据右边的表达式自动推断类型,如上面的 String 。

    var javastack = "javastack";

     

    就等于:

    String javastack = "javastack";

     

    更多使用详情请参考这篇文章《Java 10 实战第 1 篇:局部变量类型推断》,这里不再重复了。

    2、字符串加强

    Java 11 增加了一系列的字符串处理方法,如以下所示。

     

    // 判断字符串是否为空白 " ".isBlank(); // true // 去除首尾空格 " Javastack ".strip(); // "Javastack" // 去除尾部空格  " Javastack ".stripTrailing(); // " Javastack" // 去除首部空格  " Javastack ".stripLeading(); // "Javastack " // 复制字符串 "Java".repeat(3); // "JavaJavaJava" // 行数统计 "A\nB\nC".lines().count(); // 3

    3、集合加强

    自 Java 9 开始,Jdk 里面为集合(List/ Set/ Map)都添加了 of 和 copyOf 方法,它们两个都用来创建不可变的集合,来看下它们的使用和区别。

    示例1:

    var list = List.of("Java""Python""C"); var copy = List.copyOf(list); System.out.println(list == copy);  // true

    示例2:

    var list = new ArrayList<String>(); var copy = List.copyOf(list); System.out.println(list == copy);  // false

     

    来看下它们的源码:

    static <E> List<E> of(E... elements) {     switch (elements.length) { // implicit null check of elements         case 0:             return ImmutableCollections.emptyList();         case 1:             return new ImmutableCollections.List12<>(elements[0]);         case 2:             return new ImmutableCollections.List12<>(elements[0], elements[1]);         default:             return new ImmutableCollections.ListN<>(elements);     } } static <E> List<E> copyOf(Collection<? extends E> coll) {     return ImmutableCollections.listCopy(coll); } static <E> List<E> listCopy(Collection<? extends E> coll) {     if (coll instanceof AbstractImmutableList && coll.getClass() != SubList.class) {         return (List<E>)coll;     } else {         return (List<E>)List.of(coll.toArray());     } }

     

    可以看出 copyOf 方法会先判断来源集合是不是 AbstractImmutableList 类型的,如果是,就直接返回,如果不是,则调用 of 创建一个新的集合。

     

    示例2因为用的 new 创建的集合,不属于不可变 AbstractImmutableList 类的子类,所以 copyOf 方法又创建了一个新的实例,所以为false.

     注意:使用 of 和 copyOf 创建的集合为不可变集合,不能进行添加、删除、替换、排序等操作,不然会报 java.lang.UnsupportedOperationException 异常。

     

    上面演示了 List 的 of 和 copyOf 方法,Set 和 Map 接口都有。

    4、Stream 加强

    Stream 是 Java 8 中的新特性,Java 9 开始对 Stream 增加了以下 4 个新方法。

    1) 增加单个参数构造方法,可为null

    Stream.ofNullable(null).count(); // 0

    2) 增加 takeWhile 和 dropWhile 方法

    Stream.of(12321)     .takeWhile(n -> n < 3)     .collect(Collectors.toList());  // [1, 2]

    从开始计算,当 n < 3 时就截止。

    Stream.of(12321)     .dropWhile(n -> n < 3)     .collect(Collectors.toList());  // [3, 2, 1]

     

    这个和上面的相反,一旦 n < 3 不成立就开始计算。

     

    3)iterate重载

     

    这个 iterate 方法的新重载方法,可以让你提供一个 Predicate (判断条件)来指定什么时候结束迭代。

     

    如果你对 JDK 8 中的 Stream 还不熟悉,可以看之前分享的这一系列教程。

    5、Optional 加强

    Opthonal 也增加了几个非常酷的方法,现在可以很方便的将一个 Optional 转换成一个 Stream, 或者当一个空 Optional 时给它一个替代的。

     

    Optional.of("javastack").orElseThrow();     // javastack Optional.of("javastack").stream().count();  // 1 Optional.ofNullable(null)     .or(() -> Optional.of("javastack"))     .get();   // javastack

    6、InputStream 加强

    InputStream 终于有了一个非常有用的方法:transferTo,可以用来将数据直接传输到 OutputStream,这是在处理原始数据流时非常常见的一种用法,如下示例。

     

    var classLoader = ClassLoader.getSystemClassLoader(); var inputStream = classLoader.getResourceAsStream("javastack.txt"); var javastack = File.createTempFile("javastack2""txt"); try (var outputStream = new FileOutputStream(javastack)) {     inputStream.transferTo(outputStream); }

    7、HTTP Client API

    这是 Java 9 开始引入的一个处理 HTTP 请求的的孵化 HTTP Client API,该 API 支持同步和异步,而在 Java 11 中已经为正式可用状态,你可以在 java.net 包中找到这个 API。

     

    一、JDK11新特性一览

    181: Nest-Based Access Control309: Dynamic Class-File Constants315: Improve Aarch64 Intrinsics318: Epsilon: A No-Op Garbage Collector320: Remove the Java EE and CORBA Modules321: HTTP Client (Standard)323: Local-Variable Syntax for Lambda Parameters324: Key Agreement with Curve25519 and Curve448327: Unicode 10328: Flight Recorder329: ChaCha20 and Poly1305 Cryptographic Algorithms330: Launch Single-File Source-Code Programs331: Low-Overhead Heap Profiling332: Transport Layer Security (TLS) 1.3333: ZGC: A Scalable Low-Latency Garbage Collector (Experimental)335: Deprecate the Nashorn JavaScript Engine336: Deprecate the Pack200 Tools and API

    二、JDK11发布计划

    日期阶段说明2018/06/28Rampdown Phase One (fork from main line)对进入Rampdown阶段的变化会应用越来越严格的审查。在阶段1中,只能修复 P1-P3 错误。2018/07/26Rampdown Phase Two在阶段2中,只能修复 showstopper 错误2018/08/16Initial Release Candidate2018/08/30Final Release Candidate在此阶段必须宣布最终候选版的发布日期并提交以进行测试2018/09/25General Availability最终版本,可在生产环境正式使用

    三、JDK11特性解读

    JEP 181: Nest-Based Access Control(基于嵌套的访问控制)

    JEP 309: Dynamic Class-File Constants(动态类文件常量)

    Java的类型文件格式将被拓展,支持一种新的常量池格式:CONSTANT_Dynamic,加载CONSTANT_Dynamic会将创建委托给bootstrap方法。

    目标

    其目标是降低开发新形式的可实现类文件约束带来的成本和干扰。

    JEP 315: Improve Aarch64 Intrinsics(改进 Aarch64 函数)

    JEP 318: Epsilon: A No-Op Garbage Collector(Epsilon — 一个无操作的垃圾收集器)

    JDK上对这个特性的描述是:开发一个处理内存分配但不实现任何实际内存回收机制的GC,一旦可用堆内存用完,JVM就会退出。

    如果有System.gc()的调用,实际上什么也不会发生(这种场景下和-XX:+DisableExplicitGC效果一样),因为没有内存回收,这个实现可能会警告用户尝试强制GC是徒劳。

    用法非常简单:

    -XX:+UseEpsilonGC。

    动机

    提供完全被动的GC实现,具有有限的分配限制和尽可能低的延迟开销,但代价是内存占用和内存吞吐量。

    众所周知,Java实现可广泛选择高度可配置的GC实现。 各种可用的收集器最终满足不同的需求,即使它们的可配置性使它们的功能相交。 有时更容易维护单独的实现,而不是在现有GC实现上堆积另一个配置选项。

    它的主要用途如下:

    性能测试(它可以帮助过滤掉GC引起的性能假象);内存压力测试(例如,知道测试用例应该分配不超过1 GB的内存,我们可以使用-Xmx1g配置-XX:+UseEpsilonGC,如果违反了该约束,则会heap dump并崩溃);非常短的JOB任务(对于这种任务,接受GC清理堆那都是浪费空间);VM接口测试;Last-drop 延迟&吞吐改进;

    JEP 320: Remove the Java EE and CORBA Modules(删除 Java EE 和 CORBA 模块)

    Java EE和CORBA两个模块在JDK9中已经标记"deprecated",在JDK11中正式移除。JDK中deprecated的意思是在不建议使用,在未来的release版本会被删除。

    动机

    JavaEE由4部分组成:

    JAX-WS (Java API for XML-Based Web Services),JAXB (Java Architecture for XML Binding)JAF (the JavaBeans Activation Framework)Common Annotations.

    但是这个特性和JavaSE关系不大。并且JavaEE被维护在Github(https://github.com/javaee)中,版本同步造成维护困难。最后,JavaEE可以单独引用,maven中心仓库也提供了JavaEE(http://mvnrepository.com/artifact/javax/javaee-api/8.0),所以没必要把JavaEE包含到JavaSE中。

    至于CORBA,使用Java中的CORBA开发程序没有太大的兴趣。因此,在JavaEE就把CORBA标记为"Proposed Optional",这就表明将来可能会放弃对这些技术的必要支持。

    JEP 321: HTTP Client (Standard)(标准HTTP客户端)

    将JDK9引进并孵化的HTTP客户端API作为标准,即HTTP/2 Client。它定义了一个全新的实现了HTTP/2和WebSocket的HTTP客户端API,并且可以取代HttpURLConnection。 动机

    已经存在的HttpURLConnection有如下问题:

    在设计时考虑了多种协议,但是现在几乎所有协议现已不存在。API早于HTTP/1.1并且太抽象;使用很不友好;只能以阻塞模式工作;非常难维护;

    JEP 323: Local-Variable Syntax for Lambda Parameters(用于 Lambda 参数的局部变量语法)

    在声明隐式类型的lambda表达式的形参时允许使用var。

    动机

    lamdba表达式可能是隐式类型的,它形参的所有类型全部靠推到出来的。隐式类型lambda表达式如下:

    (x, y) -> x.process(y)

    Java SE 10让隐式类型变量可用于本地变量:

    var foo = new Foo(); for (var foo : foos) { ... } try (var foo = ...) { ... } catch ...

    为了和本地变量保持一致,我们希望允许var作为隐式类型lambda表达式的形参:

    (var x, var y) -> x.process(y)

    统一格式的一个好处就是modifiers和notably注解能被加在本地变量和lambda表达式的形参上,并且不会丢失简洁性:

    @Nonnull var x = new Foo(); (@Nonnull var x, @Nullable var y) -> x.process(y)

    JEP 324: Key Agreement with Curve25519 and Curve448(Curve25519 和 Curve448 算法的密钥协议)

    用RFC 7748中描述到的 Curve25519 和Curve448 实现秘钥协议。RFC 7748定义的秘钥协商方案更高效,更安全。这个JEP的主要目标就是为这个标准定义API和实现。

    动机

    密码学要求使用 Curve25519 和Curve448 是因为它们的安全性和性能。JDK会增加两个新的接口XECPublicKey 和 XECPrivateKey,示例代码如下:

    KeyPairGenerator kpg = KeyPairGenerator.getInstance("XDH"); NamedParameterSpec paramSpec = new NamedParameterSpec("X25519"); kpg.initialize(paramSpec); // equivalent to kpg.initialize(255) // alternatively: kpg = KeyPairGenerator.getInstance("X25519") KeyPair kp = kpg.generateKeyPair(); KeyFactory kf = KeyFactory.getInstance("XDH"); BigInteger u = ... XECPublicKeySpec pubSpec = new XECPublicKeySpec(paramSpec, u); PublicKey pubKey = kf.generatePublic(pubSpec); KeyAgreement ka = KeyAgreement.getInstance("XDH"); ka.init(kp.getPrivate()); ka.doPhase(pubKey, true); byte[] secret = ka.generateSecret();

    JEP 327: Unicode 10

    更新平台API支持Unicode 10.0版本(Unicode 10.0概述:Unicode 10.0 增加了8518 个字符, 总计达到了136,690个字符. 并且增加了4个脚本, 总结139个脚本, 同时还有56个新的emoji表情符号。参考:http://unicode.org/versions/Unicode10.0.0/)。

    动机

    Unicode是一个不断进化的工业标准,因此必须不断保持Java和Unicode最新版本同步。

    JEP 328: Flight Recorder(飞行记录器)

    提供一个低开销的,为了排错Java应用问题,以及JVM问题的数据收集框架,希望达到的目标如下:

    提供用于生产和消费数据作为事件的API;提供缓存机制和二进制数据格式;允许事件配置和事件过滤;提供OS,JVM和JDK库的事件;

    动机

    排错,监控,性能分析是整个开发生命周期必不可少的一部分,但是某些问题只会在大量真实数据压力下才会发生在生产环境。

    Flight Recorder记录源自应用程序,JVM和OS的事件。 事件存储在一个文件中,该文件可以附加到错误报告中并由支持工程师进行检查,允许事后分析导致问题的时期内的问题。工具可以使用API从记录文件中提取信息。

    JEP 329: ChaCha20 and Poly1305 Cryptographic Algorithms(ChaCha20 和 Poly1305 加密算法)

    实现RFC 7539中指定的 ChaCha20 和 ChaCha20-Poly1305 两种加密算法。

    动机

    唯一一个其他广泛采用的RC4长期以来一直被认为是不安全的,业界一致认为当下ChaCha20-Poly1305是安全的。

    JEP 330: Launch Single-File Source-Code Programs(启动单一文件的源代码程序)

    增强Java启动器支持运行单个Java源代码文件的程序。

    动机

    单文件程序是指整个程序只有一个源码文件,通常是早期学习Java阶段,或者写一个小型工具类。以HelloWorld.java为例,运行它之前需要先编译。我们希望Java启动器能直接运行这个源码级的程序:

    java HelloWorld.java

    等价于:

    javac -d <memory> HelloWorld.java java -cp <memory> helloWorld java Factorial.java 3 4 5

    等价于:

    javac -d <memory> Factorial.java java -cp <memory> Factorial 3 4 5

    到JDK10为止,Java启动器能以三种方式运行:

    启动一个class文件;启动一个JAR中的main方法类;启动一个模块中的main方法类;

    JDK11再加一个,即第四种方式:启动一个源文件申明的类。

    JEP 331: Low-Overhead Heap Profiling(低开销的 Heap Profiling)

    提供一种低开销的Java堆分配采样方法,得到堆分配的Java对象信息,可通过JVMTI访问。希望达到的目标如下:

    足够低的开销,可以默认且一直开启;能通过定义好的程序接口访问;能采样所有分配;能给出生存和死亡的Java对象信息; 动机

    对用户来说,了解它们堆里的内存是很重要的需求。目前有一些已经开发的工具,允许用户窥探它们的堆,比如:Java Flight Recorder, jmap, YourKit, 以及VisualVM tools.。但是这工具都有一个很大的缺点:无法得到对象的分配位置。headp dump以及heap histo都没有这个信息,但是这个信息对于调试内存问题至关重要。因为它能告诉开发者,他们的代码发生(尤其是坏的)分配的确切位置。

    JEP 332: Transport Layer Security (TLS) 1.3(支持 TLS 1.3)

    实现TLS协议1.3版本。(TLS允许客户端和服务端通过互联网以一种防止窃听,篡改以及消息伪造的方式进行通信)。

    动机

    TLS 1.3是TLS协议的重大改进,与以前的版本相比,它提供了显着的安全性和性能改进。其他供应商的几个早期实现已经可用。我们需要支持TLS 1.3以保持竞争力并与最新标准保持同步。这个特性的实现动机和Unicode 10一样,也是紧跟历史潮流。

    JEP 333: ZGC: A Scalable Low-Latency Garbage Collector (可伸缩低延迟垃圾收集器)

    ZGC:这应该是JDK11最为瞩目的特性,没有之一。但是后面带了Experimental,说明还不建议用到生产环境。看看官方对这个特性的目标描述:

    GC暂停时间不会超过10ms;即能处理几百兆小堆,也能处理几个T的大堆(OMG);和G1相比,应用吞吐能力不会下降超过15%;为未来的GC功能和利用colord指针以及Load barriers优化奠定基础;初始只支持64位系统;

    动机

    GC是Java主要优势之一。然而,当GC停顿太长,就会开始影响应用的响应时间。消除或者减少GC停顿时长,Java将对更广泛的应用场景是一个更有吸引力的平台。此外,现代系统中可用内存不断增长, 用户和程序员希望JVM能够以高效的方式充分利用这些内存,并且无需长时间的GC暂停时间。 ZGC一个并发,基于region,压缩型的垃圾收集器,只有root扫描阶段会STW,因此GC停顿时间不会随着堆的增长和存活对象的增长而变长。 ZGC和G1停顿时间比较:

    ZGC avg: 1.091ms (+/-0.215ms) 95th percentile: 1.380ms 99th percentile: 1.512ms 99.9th percentile: 1.663ms 99.99th percentile: 1.681ms max: 1.681ms G1 avg: 156.806ms (+/-71.126ms) 95th percentile: 316.672ms 99th percentile: 428.095ms 99.9th percentile: 543.846ms 99.99th percentile: 543.846ms max: 543.846ms

    用法:

    -XX:+UnlockExperimentalVMOptions -XX:+UseZGC

    因为ZGC还处于实验阶段,所以需要通过JVM参数UnlockExperimentalVMOptions 来解锁这个特性。

    JEP 335: Deprecate the Nashorn JavaScript Engine(弃用 Nashorn JavaScript 引擎)

    JEP 336: Deprecate the Pack200 Tools and API(弃用 Pack200 工具和 API)

    参考:http://openjdk.java.net/projects/jdk/11/

    https://www.jianshu.com/p/ae60abb6752d

     
    最新回复(0)