基本介绍

2020 年 3 月 17 日,JDK / Java 14 正式 GA(General Available)。这是自从 Java 采用六个月一次的发布周期之后的第五次发布。

此版本包含的 JEP Java/JDK Enhancement Proposals JDK 增强提案)比 Java 12 和 13 加起来的还要多。总共 16 个新特性,包括两个孵化器模块 、三 个预览特性、两个弃用的功能以及两个删除的功能。

  • 「孵化器模块」:将 尚未定稿的 API 和工具先交给开发者使用,以获得反馈,并用这些反馈进一步改进 Java 平台的质量。
  • 「预览特性」:是规格已经成型、实现已经确定,但还未最终定稿的功能。它们出现在 Java 中的目的是收集在真实世界中使用后的反馈信息,促进这些功能的最终定稿 。这些特性可能会随时改变,根据反馈结果, 这些特性甚至可能会被移除,但通常所有预览特性最后都会在 Java 中固定下来。

环境准备

安装 JDK 14 https://www.oracle.com/technetwork/java/javase/overview/index.html

安装编译器:IDEA 2020.1 或者 Eclipse 2020-03

新特性介绍

JEP 305:instanceof 的模式匹配(预览特性)

这个特性很有意思,因为它为更为通用的模式匹配打开了大门。模式匹配通过更为简便的语法基于一定的条件来抽取对象的组件,而 instanceof 刚好是这种情况,它先检查对象类型,然后再调用对象的方法或访问对象的字段。

在 Java 14 之前,我们使用 instanceof 是这样的

@Test
public void test01() {
Object obj = "hello java14";
if (obj instanceof String) {
String str = (String) obj;
System.out.println(str.contains("hello"));
} else {
System.out.println("不是 String 类型");
}
}

在 Java 14 中是这样的,相当于将上面的第4、5行代码简化了,省略了强制转化的过程,注意:「str 的作用域依旧是 if 结构内」

@Test
public void test02() {
Object obj = "hello java14";
if (obj instanceof String str) {
System.out.println(str.contains("hello"));
} else {
System.out.println("不是 String 类型");
}
}

有了该功能,可以减少 Java 程序中显式强制转换的数量,从而提高生产力,还能实现更精确、简洁的类型安全的代码 。

JEP 358:非常实用的 NullPointerException

该特性改进了 NullPointerException 的可读性,能更准确地给出 null 变量的信息 。

就是这个老爷子当年发明的 null,让成千上万的程序员深恶痛绝,他称自己犯了一个价值十亿美金的错误,那就是空指针!

《Java 8 实战》中是这样说的:

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

在 Java 8 中引入了 Optional,Optional 在可能为 null 的对象上做了一层封装,强制你思考值不存在的情况,这样

就能避免潜在的空指针异常 。

在 Java 14 中,对于 NPE 有了一个增强,该特性可以更好地提示哪个地方出现的空指针

需要我们在运行参数上加上 -XX:+ShowCodeDetailsInExceptionMessages 开启此功能,这个增强特性不仅适用于方法调用,只要会导致 NullPointerException 的地方也都适用,包括字段的访问、数组的访问和赋值 。

JEP 359:Record (预览特性)

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

该预览特性提供了一种更为紧凑的语法来声明类。 值得一提的是,该特性可以大幅减少定义类似数据类型时所需的样板代码。

使用 record 来减少类声明语法,效果类似 lombok 的 @Data 注解, Kotlin 中的 data class 。它们的共同点是类的部分或全部状态可以直接在类头中描述,并且这个类中只包含了纯数据而已。

我们声明一个 record 类型的类

public record Person(String name, Integer age) {
}

它编译后的 class 文件如下

public final class Person extends java.lang.Record {
private final java.lang.String name;
private final java.lang.Integer age; public Person(java.lang.String name, java.lang.Integer age) { /* compiled code */ } public java.lang.String toString() { /* compiled code */ } public final int hashCode() { /* compiled code */ } public final boolean equals(java.lang.Object o) { /* compiled code */ } public java.lang.String name() { /* compiled code */ } public java.lang.Integer age() { /* compiled code */ }
}

调用其属性的时候与普通类有所不同

@Test
public void test3(){
Person person = new Person("张三", 12);
person.name();
person.age();
}

当你用 record 声明一个类时,该类将自动拥有以下功能:

  • 获取成员变量的简单方法,以上面代码为例 name() 和 partner() 。注意区别于我们平常 getter 的写法。
  • 一个 equals 方法的实现,执行比较时会比较该类的所有成员属性
  • 重写 equals 当然要重写 hashCode
  • 一个可以打印该类所有成员属性的 toString 方法。
  • 请注意只会有一个构造方法。

和枚举类型一样,记录也是类的一种受限形式。 作为回报,记录对象在简洁性方面提供了显著的好处。

但是需要注意:

  • 可以在 Record 声明的类中定义静态字段、静态方法、构造器或实例方法。
  • 不能在 Record 声明的类中定义实例字段;类不能声明为 abstract;不能声明显式的父类等。

JEP 361:switch 表达式

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

我们使用 -> 来替代以前的 :break,另外还提供了 yield 来在 block 中返回值

代码演示:

public class SwitchExpression {
public static void main(String[] args) {
Season type = Season.AUTUMN;
String s = switch (type) {
case SPRING -> "春";
case SUMMER -> "夏";
case AUTUMN -> "秋";
case WINTER -> "冬";
default -> {
System.out.println("没有" + type + "这个选项");
yield "error";
}
};
}
enum Season {
SPRING, SUMMER, AUTUMN, WINTER
}
}

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

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

于是在 JDK13 中引入了 text blocks,JDK 14 进行了第二轮 preview,JDK14 的版本主要增加了两个功能,分别是\\s

例如我们要写一个 sql 语句,使用普通的字符串是这样的,这是比较简单的语句,如果复杂一点,简直不堪入目

@Test
public void test1() {
String sql =
"SELECT name, age\n" +
"FROM user\n" +
"WHERE age = 19";
System.out.println(sql);
}

使用了代码块是这样的,可读性变高了

@Test
public void test2(){
String sql = """
SELECT name, age
FROM user
WHERE age = 19
""";
System.out.println(sql);
}

但是运行上述代码可以看出,代码块里写的是什么格式就会输出什么格式,如果我们想让它只输出一行,可读性也高呢?

这时,我们可以使用 JDK 14 新加的 \(取消换行)和 \s(一个空格)

@Test
public void test3(){
String sql = """
SELECT name, age \
FROM user\s\
WHERE age = 19\s\
""";
System.out.println(sql);
}

JEP 366 :弃用 ParallelScavenge 和 SerialOld GC 组合

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 都会出现如下警告:

Java HotSpot(TM) 64 Bit Server VM warning: Option UseParallelOldGC was deprecated in version 14.0 and will likely be removed in a future release.

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 信息。

JEP:ZGC on macOS and windows

先看一下 ZGC 的恐怖性能,它可以在尽可能对吞吐量影响不大的前提下,实现在任意堆内存大小下都可以把垃圾收集的停顿时间限制在十毫秒以内的低延迟。

JEP 364:ZGC 应用在 macOS 上、JEP 365:ZGC 应用在 Windows 上

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

使用方式:-XX:+UnlockExperimentalVMOptions -XX:+UseZGC

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


有几个不重要的新特性没有列举,可自行查看相关资料

本文大部分的资料来源于此视频的课件:https://www.bilibili.com/video/BV1tC4y147US

Java14:你需要知道的新特性的更多相关文章

  1. Spring Boot 2.3.0正式发布:优雅停机、配置文件位置通配符新特性一览

    当大潮退去,才知道谁在裸泳..关注公众号[BAT的乌托邦]开启专栏式学习,拒绝浅尝辄止.本文 https://www.yourbatman.cn 已收录,里面一并有Spring技术栈.MyBatis. ...

  2. 一文带你看遍 JDK9~14 的重要新特性!

    Java9 发布于 2017 年 9 月 21 日 .作为 Java8 之后 3 年半才发布的新版本,Java 9 带 来了很多重大的变化其中最重要的改动是 Java 平台模块系统的引入,其他还有诸如 ...

  3. 从Java 9 到 Java 17 新特性梳理

    Java 9 新的创建集合的方法  // [1, 2, 3, 4]  List<Integer> integers = List.of(1, 2, 3, 4);  // {1,2,3}   ...

  4. SQL Server 2014 新特性——内存数据库

    SQL Server 2014 新特性——内存数据库 目录 SQL Server 2014 新特性——内存数据库 简介: 设计目的和原因: 专业名词 In-Memory OLTP不同之处 内存优化表 ...

  5. ElasticSearch 5学习(10)——结构化查询(包括新特性)

    之前我们所有的查询都属于命令行查询,但是不利于复杂的查询,而且一般在项目开发中不使用命令行查询方式,只有在调试测试时使用简单命令行查询,但是,如果想要善用搜索,我们必须使用请求体查询(request ...

  6. [干货来袭]C#6.0新特性

    微软昨天发布了新的VS 2015 ..随之而来的还有很多很多东西... .NET新版本 ASP.NET新版本...等等..太多..实在没消化.. 分享一下也是昨天发布的新的C#6.0的部分新特性吧.. ...

  7. CSS3新特性应用之结构与布局

    一.自适应内部元素 利用width的新特性min-content实现 width新特性值介绍: fill-available,自动填充盒子模型中剩余的宽度,包含margin.padding.borde ...

  8. 【译】Meteor 新手教程:在排行榜上添加新特性

    原文:http://danneu.com/posts/6-meteor-tutorial-for-fellow-noobs-adding-features-to-the-leaderboard-dem ...

  9. 跨平台的 .NET 运行环境 Mono 3.2 新特性

    Mono 3.2 发布了,对 Mono 3.0 和 2.10 版本的支持不再继续,而且这两个分支也不再提供 bug 修复更新. Mono 3.2 主要新特性: LLVM 更新到 3.2 版本,带来更多 ...

随机推荐

  1. MyBatis框架——多表查询

    MyBatis多表查询, 从表中映射主表,使用 association 标签,通过设置 javaType 属性关联实体类: 主表映射从表,使用 collection 标签,通过 ofType 属性关联 ...

  2. 从零开始学习R语言(五)——数据结构之“列表(List)”

    本文首发于知乎专栏:https://zhuanlan.zhihu.com/p/60141740 也同步更新于我的个人博客:https://www.cnblogs.com/nickwu/p/125678 ...

  3. SpringBoot2 线程池的定义和使用

    SpringBoot2 线程池的定义和使用 定义线程池 @Slf4j @EnableAsync @Configuration public class AsyncExecutorConfig impl ...

  4. VSCode 配置C++开发环境

    目录 安装VSCode应用程序 安装相关插件 汉化插件 C++编辑器插件 编写配置文件 tasks.json launch.json c_cpp_properties.json 第一步.安装VSCod ...

  5. vue 组件通讯方式到底有多少种 ?

    前置 做大小 vue 项目都离不开组件通讯, 自己也收藏了很多关于 vue 组件通讯的文章. 今天自己全部试了试, 并查了文档, 在这里总结一下并全部列出, 都是简单的例子. 如有错误欢迎指正. 温馨 ...

  6. java基础-对集合(Collection)的总结

    集合(Collection)类型也是Java标准库中被使用最多的类型. List ArrayList LinkedList 对于自定义的对象,需要正确覆写 equals方法 参看7.3 例子 Map ...

  7. 拜托,别再问我什么是 B+ 树了

    前言 每当我们执行某个 SQL 发现很慢时,都会下意识地反应是否加了索引,那么大家是否有想过加了索引为啥会使数据查找更快呢,索引的底层一般又是用什么结构存储的呢,相信大家看了标题已经有答案了,没错!B ...

  8. 五、运算符的补充与if语句

    1.可变不可变类型 指:对前面所学类型做一个可变和不可变类型的分类 可变类型:值改变,ID不变,证明改的是原值,原值是可以被改变的 不可变类型:值改变,ID也变了,证明是产生新的值,压根没有改变原值, ...

  9. 模板字符串原理,原生js实现字符串模板

    在使用模板字符串的时候使用的是 '{{}}'形式进行书写,本文则向各位解密这么写的原因 初体验正则 首先要先明白正则表达式中exec的使用 例如: let str = 'axu1997@qq.com' ...

  10. 关于《自动化测试实战宝典:Robot Framework + Python从小工到专家》

    受新冠疫情影响,笔者被“困”在湖北老家七十余天,于4月1号(愚人节)这天,终于返回到广州.当前国内疫情基本已趋于平稳,但全球疫情整体势态仍在持续疯涨,累计确诊病例已近80万人.祈祷这场全球性灾难能尽早 ...