post:完成Java 14新特性文章。
This commit is contained in:
parent
0fcf7812f2
commit
a3cffb0765
189
source/_posts/nf-java14.md
Normal file
189
source/_posts/nf-java14.md
Normal file
|
@ -0,0 +1,189 @@
|
|||
---
|
||||
title: Java 14的新特性
|
||||
tags:
|
||||
- JVM
|
||||
- Java
|
||||
- Java 14
|
||||
- 新特性
|
||||
- switch
|
||||
- 文本块
|
||||
- 打包
|
||||
- Package
|
||||
- Record Class
|
||||
categories:
|
||||
- - JVM
|
||||
- Java
|
||||
keywords: 'Java,Java 14,新特性,switch,文本,文本块,打包,内存,记录类'
|
||||
date: 2021-05-24 11:16:10
|
||||
---
|
||||
|
||||
Java 14带来了许多新功能,尤其是把之前一直处于预览状态的功能进行了实装。而且新加入的一些正在孵化的功能也是大大增强了Java的适用面。<!-- more -->
|
||||
|
||||
本系列的文章有:
|
||||
|
||||
- {% post_link nf-java8 %}
|
||||
- {% post_link nf-java9 %}
|
||||
- {% post_link nf-java10 %}
|
||||
- {% post_link nf-java11 %}
|
||||
- {% post_link nf-java12 %}
|
||||
- {% post_link nf-java13 %}
|
||||
- {% post_link nf-java14 %}
|
||||
- {% post_link nf-java15 %}
|
||||
- {% post_link nf-java16 %}
|
||||
|
||||
## Switch表达式
|
||||
|
||||
Switch表达式是在Java 12中以预览版的身份被添加进来的。在Java语言的历史中,`switch`关键字始终是作为一个语句出现的。例如我们经常会用到的星期枚举类。
|
||||
|
||||
```java
|
||||
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`表达式语法重写上面这个示例。
|
||||
|
||||
```java
|
||||
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`的语句。
|
||||
|
||||
```java
|
||||
int[] arr = null;
|
||||
arr[0] = 1;
|
||||
```
|
||||
|
||||
在Java 14之前的版本中,会得到以下的错误提示。
|
||||
|
||||
```
|
||||
Exception in thread "main" java.lang.NullPointerException
|
||||
at xyz.archgrid.demo.App.main(App.java:27)
|
||||
```
|
||||
|
||||
但是在Java 14中,NPE的错误提示被加强了,而且变得更加有可读性和目的性,例如上面示例中的提示就会变成下面这样。
|
||||
|
||||
```
|
||||
java.lang.NullPointerException: Cannot store to int array because "arr" is null
|
||||
```
|
||||
|
||||
## 预览版功能
|
||||
|
||||
## 文本块
|
||||
|
||||
文本块自Java 13以来还依旧处于预览状态。但是文本块功能在Java 14中增加了两个转义字符。
|
||||
|
||||
- `\`加入到文本块中,可以表示两行之间的连接,只是用于文本块中的文本产生阅读视觉上的换行,但是其中并不真正的换行。
|
||||
- `\s`表示一个空格。
|
||||
|
||||
!!! note ""
|
||||
虚拟换行`\`仅仅是防止一行字符串写的太长,但是如果直接使用换行又会导致字符串的实际换行存在的。
|
||||
|
||||
### instanceOf中的模式匹配
|
||||
|
||||
在Java 14中,移除了`instanceOf`的一些样板代码,例如在之前的版本中,如果变量的类型匹配上了,那么接下来就一定会产生如下的操作。
|
||||
|
||||
```java
|
||||
if (obj instanceof String) {
|
||||
String str = (String) obj;
|
||||
// 完成其他对于字符串变量str的操作
|
||||
}
|
||||
```
|
||||
|
||||
为了移除这个并不必要的字符串变量声明,Java 14把变量声明与`instanceOf`操作符合并了。于是就变成了下面这个样子。
|
||||
|
||||
```java
|
||||
if (obj instanceOf String str) {
|
||||
// 完成其他对于字符串变量str的操作。
|
||||
}
|
||||
```
|
||||
|
||||
### 记录类
|
||||
|
||||
在Java中定义一个POJO还是比较繁琐的,除了要定义用于保存数据的字段以外,还需要定义相应的getter和setter,必要的时候还需要重载`hashCode()`和`equals()`方法。所以这也是Lombok库能够引起大部分开发者共鸣的原因。
|
||||
|
||||
比如,借助Lombok库,我们可以这样来定义一个数据类。
|
||||
|
||||
```java
|
||||
@Data
|
||||
public class User {
|
||||
private int uid;
|
||||
private String username;
|
||||
private String password;
|
||||
}
|
||||
```
|
||||
|
||||
为了简化POJO的书写,也是从其他语言中借鉴,Java 14引入了一个名为记录类的预览版功能。这是一个新的关键字`record`,它用来声明一个特殊的类,效果与使用Lombok的`@Data`修饰的普通类几乎相同。
|
||||
|
||||
如果使用`record`关键字,那么上面这个示例就可以被改写成下面这个样子。
|
||||
|
||||
```java
|
||||
public record User(int uid, String username, String password) { }
|
||||
```
|
||||
|
||||
整个POJO类的声明就被简化成了类似于构造函数的样子,那么现在这个类就可以如同以下示例中这样来使用了。
|
||||
|
||||
```java
|
||||
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的功能主要是通过`MemorySegment`、`MemoryAddress`和`MemoryLayout`这几个类来提供的,可以允许程序同时访问堆内存和非堆内存。
|
||||
|
||||
### 打包工具
|
||||
|
||||
传统上Java程序所遵循的都是“Build once, run everywhere”的跨平台理念。在这个历年的支持下,Java程序一般都是以JAR包的形式出现和发布,在运行的时候都需要提供提供JAR运行所需的JVM环境。这也就是说用户至少需要在他们的机器上安装JRE。
|
||||
|
||||
但是无论是在Windows、macOS还是在Linux上,很多程序都是以安装包的形式出现的,用户只需要运行安装包,就可以把程序安装到系统中,并且可以直接拥有启动程序的快捷方式。
|
||||
|
||||
用户所期望的这些程序安装方式,Java都不能提供。所以在Java 14中,将一套专门的打包工具列入了孵化项目。
|
||||
|
||||
在这套工具中,常用的有两个工具:`jlink`和`jpackage`。其中`jlink`主要用于JDK和JRE的裁剪,仅为程序保留程序运行所需的最小模块。`jpackage`主要用来对程序和裁剪过后的JRE进行打包,形成可执行文件(例如Windows中的`.exe`,macOS中的`.app`),并同时形成相应的安装包。
|
||||
|
||||
打包工具的出现将极大的改变Java程序的发布和部署。
|
Loading…
Reference in New Issue
Block a user