Java 14的新特性

发布时间:2021-05-24 11:16
最后更新:2021-05-24 11:16
所属分类:
JVM Java

Java 14带来了许多新功能,尤其是把之前一直处于预览状态的功能进行了实装。而且新加入的一些正在孵化的功能也是大大增强了Java的适用面。

本系列的文章有:

  1. Java 8的新特性
  2. Java 9的新特性
  3. Java 10的新特性
  4. Java 11的新特性
  5. Java 12的新特性
  6. Java 13的新特性
  7. Java 14的新特性
  8. Java 15的新特性
  9. Java 16的新特性
  10. Java 17的新特性
  11. Java 18的新特性

Switch表达式

Switch表达式是在Java 12中以预览版的身份被添加进来的。在Java语言的历史中,switch关键字始终是作为一个语句出现的。例如我们经常会用到的星期枚举类。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public enum WeekDay {
    MONDAY, TUESDAY, WEDNESDAY, THUSDAY, FRIDAY, SATURDAY, SUNDAY;

    public bool isHoliday() {
        boolean isTodayHoliday = false;
        swtich (this) {
            case MONDAY:
            case TUESDAY:
            case WEDNESDAY:
            case THUSDAY:
            case FRIDAY:
                isTodayHoliday = false;
                break;
            case SATURDAY:
            case SUNDAY:
                isTodayHoliday = true;
                break;
            default:
                throw new IllegalArgumentException("Illegal days");
        }
        return isTodayHoliday;
    }
}

在这个示例中,用到了一个中间缓存变量来保存判断结果,而且整个switch结构还使用了fall-through的特性。这些特性集中在一起,就十分容易让开发人员犯各种错误。新版的switch结构被改成了一个表达式,而且还没有了fall-through带来的缺点,语法整体也被精简了许多。

下面这个示例是使用switch表达式语法重写上面这个示例。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
public enum WeekDay {
    MONDAY, TUESDAY, WEDNESDAY, THUSDAY, FRIDAY, SATURDAY, SUNDAY;

    public bool isHoliday() {
        return switch (this) {
            case MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY -> false;
            case SATURDAY, SUNDAY -> true;
            default -> throw new IllegalArgumentException("Illegal days");
        };
    }
}

改进的NPE提示

例如有以下会产生NullPointerException的语句。

1
2
int[] arr = null;
arr[0] = 1;

在Java 14之前的版本中,会得到以下的错误提示。

1
2
Exception in thread "main" java.lang.NullPointerException
at xyz.archgrid.demo.App.main(App.java:27)

但是在Java 14中,NPE的错误提示被加强了,而且变得更加有可读性和目的性,例如上面示例中的提示就会变成下面这样。

1
java.lang.NullPointerException: Cannot store to int array because "arr" is null

预览版功能

文本块

文本块自Java 13以来还依旧处于预览状态。但是文本块功能在Java 14中增加了两个转义字符。

  • \加入到文本块中,可以表示两行之间的连接,只是用于文本块中的文本产生阅读视觉上的换行,但是其中并不真正的换行。
  • \s表示一个空格。
虚拟换行\仅仅是防止一行字符串写的太长,但是如果直接使用换行又会导致字符串的实际换行存在的。

instanceOf中的模式匹配

在Java 14中,移除了instanceOf的一些样板代码,例如在之前的版本中,如果变量的类型匹配上了,那么接下来就一定会产生如下的操作。

1
2
3
4
if (obj instanceof String) {
    String str = (String) obj;
    // 完成其他对于字符串变量str的操作
}

为了移除这个并不必要的字符串变量声明,Java 14把变量声明与instanceOf操作符合并了。于是就变成了下面这个样子。

1
2
3
if (obj instanceOf String str) {
    // 完成其他对于字符串变量str的操作。
}

记录类

在Java中定义一个POJO还是比较繁琐的,除了要定义用于保存数据的字段以外,还需要定义相应的getter和setter,必要的时候还需要重载hashCode()equals()方法。所以这也是Lombok库能够引起大部分开发者共鸣的原因。

比如,借助Lombok库,我们可以这样来定义一个数据类。

1
2
3
4
5
6
@Data
public class User {
    private int uid;
    private String username;
    private String password;
}

为了简化POJO的书写,也是从其他语言中借鉴,Java 14引入了一个名为记录类的预览版功能。这是一个新的关键字record,它用来声明一个特殊的类,效果与使用Lombok的@Data修饰的普通类几乎相同。但记录类的设计主旨是用于持有不可变数据的,所以其在使用的时候,还需要与以前的POJO区别开。

如果使用record关键字,那么上面这个示例就可以被改写成下面这个样子。

1
public record User(int uid, String username, String password) { }

整个POJO类的声明就被简化成了类似于构造函数的样子,那么现在这个类就可以如同以下示例中这样来使用了。

1
2
3
4
User user = new User(0, "John", "123");

assertEquals(0, user.id());
assertEquals("John", user.username());

可以看出,记录类中的字段都被转换成了方法,可以通过方法的调用来获取字段的值。而且记录类会自动提供hashCode()equals()toString()方法。

孵化功能

孵化功能与预览功能不同,这些功能比预览功能更加的实验性。孵化功能一般都被放置于jdk.incubator包中。

外部内存访问

外部内存访问API提供了程序对于JVM以外的系统内存的访问能力。这套API允许Java程序用十分安全、有效率的途径来访问外部内存。

新的外部内存访问API的功能主要是通过MemorySegmentMemoryAddressMemoryLayout这几个类来提供的,可以允许程序同时访问堆内存和非堆内存。

打包工具

传统上Java程序所遵循的都是“Build once, run everywhere”的跨平台理念。在这个历年的支持下,Java程序一般都是以JAR包的形式出现和发布,在运行的时候都需要提供提供JAR运行所需的JVM环境。这也就是说用户至少需要在他们的机器上安装JRE。

但是无论是在Windows、macOS还是在Linux上,很多程序都是以安装包的形式出现的,用户只需要运行安装包,就可以把程序安装到系统中,并且可以直接拥有启动程序的快捷方式。

用户所期望的这些程序安装方式,Java都不能提供。所以在Java 14中,将一套专门的打包工具列入了孵化项目。

在这套工具中,常用的有两个工具:jlinkjpackage。其中jlink主要用于JDK和JRE的裁剪,仅为程序保留程序运行所需的最小模块。jpackage主要用来对程序和裁剪过后的JRE进行打包,形成可执行文件(例如Windows中的.exe,macOS中的.app),并同时形成相应的安装包。

打包工具的出现将极大的改变Java程序的发布和部署。


索引标签
JVM
Java
Java 14
新特性
switch
文本块
打包
Package
Record Class