IDEA支持

image.png
可以看到,IDEA从14才开始支持Switch表达式,15才支持文本块

测试14支持Switch语法

  1. package com.dance;
  2. public class SwitchTest {
  3. public static void main(String[] args) {
  4. String x = "3";
  5. int i = switch (x){
  6. case "1" -> 1;
  7. case "2" -> 2;
  8. default -> 3;
  9. };
  10. System.out.println(i);
  11. int j = switch (x){
  12. case "1":
  13. yield 1;
  14. case "2":
  15. yield 2;
  16. default:
  17. yield 3;
  18. };
  19. System.out.println(j);
  20. }
  21. }

image.png
运行成功

测试14支持文本块语法

image.png
显然,他还是不支持的上面截图说明了15才支持
由此可以发现,IDEA不会支持预览语法,只有在正式确立之后才会支持

JEP 305: instanceof的模式匹配

这个特性很有意思,因为它为更为通用的模式匹配打开了大门。模式匹配通过更为简便的语法基于一定的条件来抽取对象的组件,而instanceof 刚好是这种情况,它先检查对象类型,然后再调用对象的方法或访问对象的字段。
有了该功能,可以减少Java程序中显式强制转换的数量,从而提高生产力,还能实现更精确、简洁的类型安全的代码。
image.png
image.png
本来想试试,但是显然,14IDEA是不支持的

JEP 358: NullPointException

该特性改进了NullPointerException的可读性,能更准确地给出null变量的信息。
该特性可以帮助开发者提高生产力,以及改进各种开发工具和调试工具的质量。一个目标是减少开发人员的困惑和担忧。
image.png
相信很多Java程序员都一样对null和NPE深恶痛绝,因为他确实会带来各种各样的问题(来自《Java 8 实战》)。如:

  • 它是错误之源。NullPointerException是目前Java程序开发中最典型的异常。它会使你的代码膨胀。
  • 它让你的代码充斥着深度嵌套的null检查,代码的可读性糟糕透顶。
  • 它自身是毫无意义的。null自身没有任何的语义,尤其是它代表的是在静态类型语言中以一种错误的方式对缺失变量值的建模。
  • 它破坏了Java的哲学。Java一直试图避免让程序员意识到指针的存在,唯一的例外是:null指针。
  • 它在Java的类型系统上开了个口子。null并不属于任何类型,这意味着它可以被赋值给任意引用类型的变量。这会导致问题,原因是当这个变量被传递到系统中的另一个部分后,你将无法获知这个null变量最初赋值到底是什么类型。

    其他语言如何解决NPE问题

  • 在Groovy中使用安全导航操作符(Safe Navigation Operator)可以访问可能为null的变量:

  • image.png
  • 在Haskell和Scala也有类似的替代品,如Haskell中的Maybe类型、Scala中的Option[A]。Option[A] 是一个类型为A 的可选值的容器
  • 在Kotlin 中,其类型系统严格区分一个引用可以容纳null 还是不能容纳。也就是说,一个变量是否可空必须显示声明,对于可空变量,在访问其成员时必须做空处理,否则无法编译通过:
  • image.png

    Java做了那些努力

  • 首先在Java 8中提供了Optional

    • Optional在可能为null的对象上做了一层封装,强制你思考值不存在的情况,这样就能避免潜在的空指针异常
    • 关于Optional的用法,不是本文的重点。在日常开发中经常结合Stream一起使用Optional,还是比较好用的
  • 另外一个值得一提的就是最近(2020年03月17日)发布的JDK 14中对于NPE有了一个增强。那就是JEP 358: Helpful NullPointerExceptions

    • 该特性可以更好地提示哪个地方出现的空指针,需要通过-XX:+ShowCodeDetailsInExceptionMessages开启
    • 在未来的版本中,这个特性可能会默认启用。
    • 这个增强特性不仅适用于方法调用,只要会导致NullPointerException 的地方也都适用,包括字段的访问、数组的访问和赋值。

      JEP 359: Record(预览特性)

      官方吐糟最为致命

      早在2019年2月份,Java 语言架构师Brian Goetz,曾经写过一篇文章,详尽的说明了并吐槽了Java语言,他和很多程序员一样抱怨“Java太啰嗦”或有太多的“繁文缛节”,他提到:开发人员想要创建纯数据载体类(plain data carriers)通常都必须编写大量低价值、重复的、容易出错的代码。如:构造函数、getter/setter、equals()、hashCode()以及toString()等。
      以至于很多人选择使用IDE的功能来自动生成这些代码。还有一些开发会选择使用一些第三方类库,如Lombok等来生成这些方法,从而会导致了令人吃惊的表现(surprising behavior)和糟糕的可调试性(poor debuggability)。

      神说要用Record,于是就有了

  • 我们有时候需要编写许多低价值的重复代码来实现一个简单的数据载体类:构造函数,访问器,equals(),hashCode() ,toString()等。为了避免这种重复代码,Java 14推出record。

  • Java14也许最令人兴奋,同时也是最令人惊讶的创新就是:Record类型的引入。
  • 使用record来减少类声明语法,效果类似lombok的@Data 注解,Kotlin中的data class。它们的共同点是类的部分或全部状态可以直接在类头中描述,并且这个类中只包含了纯数据而已。
  • 该预览特性提供了一种更为紧凑的语法来声明类。值得一提的是,该特性可以大幅减少定义类似数据类型时所需的样板代码
  • 当你用record声明一个类时,该类将自动拥有以下功能:
    • 获取成员变量的简单方法,以上面代码为例name() 和partner() 。注意区别于我们平常getter的写法
    • 一个equals 方法的实现,执行比较时会比较该类的所有成员属性
    • 重写equals 当然要重写hashCode
    • 一个可以打印该类所有成员属性的toString 方法。
    • 请注意只会有一个构造方法
  • 和枚举类型一样,记录也是类的一种受限形式。作为回报,记录对象在简洁性方面提供了显著的好处。
    • Enum interface
  • 还可以在Record声明的类中定义静态字段、静态方法、构造器或实例方法
  • 不能在Record声明的类中定义实例字段;类不能声明为abstract;不能声明显式的父类等。
  • 为了在Java 14中引入这种新类型,需要在Java.lang.Class对象中添加如下两个新方法:

    • RecordComponent[] getRecordComponents()
    • boolean isRecord()

      JEP 361: Switch表达式

  • 这是JDK 12和JDK 13中的预览特性,现在是正式特性了。

  • 该特性规定,switch可以当作语句使用,也可以当作表达式使用。
  • 这可以简化日常的编码方式,也为本版本中预览的模式匹配(JEP 305)特性打下了基础。
  • 具体情况:使用->来替代以前的:+break;另外还提供了yield来在block中返回值

    JEP 368: 文本块(预览第二版)

  • JDK13引入的text blocks进行第二轮preview,JDK14的版本主要增加了两个escape sequences,分别是\与\s escape sequence

  • 现实问题
    • 在Java中,通常需要使用String类型表达HTML,XML,SQL或JSON等格式的字符串,在进行字符串赋值时需要进行转义和连接操作,然后才能编译该代码,这种表达方式难以阅读并且难以维护。
  • 目标

    • 简化跨越多行的字符串,避免对换行等特殊字符进行转义,简化编写Java程序。
    • 增强Java程序中用字符串表示的其他语言的代码的可读性
    • 解析新的转义序列

      EP 366:弃用ParallelScavenge和SerialOld GC组合

      image.png
  • JDK官方给出将这个GC组合标记为Deprecate的理由是:这个GC组合需要大量的代码维护工作,并且,这个GC组合很少被使用。因为它的使用场景应该是一个很大的Young区配合一个很小的Old区,这样的话,Old区用SerialOldGC去收集时停顿时间我们才能勉强接受。

  • 废弃了parallel young generation GC与SerialOld GC的组合( -XX:+UseParallelGC与-XX:-UseParallelOldGC配合开启),现在使用-XX:+UseParallelGC -XX:-UseParallelOldGC或者-XX:-UseParallelOldGC都会出现告警如下:
  • image.png

    JEP 363: 删除CMS垃圾收集器

  • 该来的总会来,自从G1(基于Region分代)横空出世后,CMS在JDK9中就被标记为Deprecate了(JEP 291: Deprecate the Concurrent Mark Sweep (CMS) Garbage Collector)

  • CMS的弊端:
    • 1.会产生内存碎片,导致并发清除后,用户线程可用的空间不足。
    • 2.既然强调了并发(Concurrent),CMS收集器对CPU资源非常敏感
    • 3.CMS 收集器无法处理浮动垃圾
  • 上述的这些问题,尤其是碎片化问题,给你的JVM实例就像埋了一颗炸弹。说不定哪次就在你的业务高峰期来一次FGC。当CMS停止工作时,会把Serial Old GC 作为备选方案,而Serial Old GC 是JVM中性能最差的垃圾回收方式,停顿个几秒钟,上十秒都有可能。
  • 移除了CMS垃圾收集器,如果在JDK14中使用-XX:+UseConcMarkSweepGC的话,JVM不会报错,只是给出一个warning信息。
  • 现在G1回收器已成为默认回收器好几年了
  • 我们还看到了引入了两个新的收集器:ZGC (JDK11出现)和Shenandoah(open jdk12)。
    • 主打特点:低停顿时间

image.png

8-9. JEP:ZGC on macOS和windows

  • 令人震惊、革命性的ZGC
  • ZGC与Shenandoah目标高度相似,在尽可能对吞吐量影响不大的前提下,实现在任意堆内存大小下都可以把垃圾收集的停顿时间限制在十毫秒以内的低延迟。
  • 《深入理解Java虚拟机》一书中这样定义ZGC:ZGC收集器是一款基于Region内存布局的,(暂时)不设分代的,使用了读屏障、染色指针和内存多重映射等技术来实现可并发的标记-压缩算法的,以低延迟为首要目标的一款垃圾收集器。

image.png
image.png
虽然ZGC还在试验状态,没有完成所有特性,但此时性能已经相当亮眼,用“令人震惊、革命性”来形容,不为过。未来将在服务端、大内存、低延迟应用的首选垃圾收集器。
image.png

JEP 364:ZGC应用在macOS上

JEP 365:ZGC应用在Windows上

  • JDK14之前,ZGC仅Linux才支持。
  • 尽管许多使用ZGC的用户都使用类Linux的环境,但在Windows和macOS上,人们也需要ZGC进行开发部署和测试。许多桌面应用也可以从ZGC中受益。因此,ZGC特性被移植到了Windows和macOS上。
  • 现在mac或Windows上也能使用ZGC了,示例如下:-XX:+UnlockExperimentalVMOptions-XX:+UseZGC

    其他新特性

    JEP 343:打包工具(孵化器模块)

  • 这个孵化器工具为开发者带来了一种打包Java应用的方式,目的在于创建一个简单的打包工具,可以用于构建exe、pkg、dmg、deb、rpm格式的安装文件。

  • JDK14引入了jdk.incubator.jpackage.jmod,它基于JavaFX javapackager tool构建。

    JEP 345:G1的NUMA-Aware的内存分配

    image.png

    JEE 349:JFR事件流

    image.png

    JEP 352:非易失性映射字节缓冲区

    image.png
    image.png

    写在最后

    JDK 14 性能提升,但JDK 8 仍是最强王者!image.png

    image.png