mirror of
https://github.com/Snailclimb/JavaGuide
synced 2025-06-16 18:10:13 +08:00
[docs update]完善Java新特性讲解
This commit is contained in:
parent
250341c59f
commit
eb51143b87
@ -56,9 +56,9 @@ System.out.println(result);
|
|||||||
|
|
||||||
#### record 关键字
|
#### record 关键字
|
||||||
|
|
||||||
`record` 关键字可以简化 **数据类**(一个 Java 类一旦实例化就不能再修改)的定义方式,使用 `record` 代替 `class` 定义的类,只需要声明属性,就可以在获得属性的访问方法,以及 `toString()`,`hashCode()`, `equals()`方法
|
`record` 关键字可以简化 **数据类**(一个 Java 类一旦实例化就不能再修改)的定义方式,使用 `record` 代替 `class` 定义的类,只需要声明属性,就可以在获得属性的访问方法,以及 `toString()`,`hashCode()`, `equals()`方法。
|
||||||
|
|
||||||
类似于使用 `class` 定义类,同时使用了 lombok 插件,并打上了`@Getter,@ToString,@EqualsAndHashCode`注解
|
类似于使用 `class` 定义类,同时使用了 lombok 插件,并打上了`@Getter,@ToString,@EqualsAndHashCode`注解。
|
||||||
|
|
||||||
```java
|
```java
|
||||||
/**
|
/**
|
||||||
|
@ -5,7 +5,7 @@ tag:
|
|||||||
- Java新特性
|
- Java新特性
|
||||||
---
|
---
|
||||||
|
|
||||||
JDK 19 定于 9 月 20 日正式发布以供生产使用,非长期支持版本。不过,JDK 19 中有一些比较重要的新特性值得关注。
|
JDK 19 定于 2022 年 9 月 20 日正式发布以供生产使用,非长期支持版本。不过,JDK 19 中有一些比较重要的新特性值得关注。
|
||||||
|
|
||||||
JDK 19 只有 7 个新特性:
|
JDK 19 只有 7 个新特性:
|
||||||
|
|
||||||
|
@ -18,8 +18,8 @@ JDK 20 只有 7 个新特性:
|
|||||||
- [JEP 433:switch 模式匹配](https://openjdk.org/jeps/433)(第四次预览)
|
- [JEP 433:switch 模式匹配](https://openjdk.org/jeps/433)(第四次预览)
|
||||||
- [JEP 434: Foreign Function & Memory API(外部函数和内存 API)](https://openjdk.org/jeps/434)(第二次预览)
|
- [JEP 434: Foreign Function & Memory API(外部函数和内存 API)](https://openjdk.org/jeps/434)(第二次预览)
|
||||||
- [JEP 436: Virtual Threads(虚拟线程)](https://openjdk.org/jeps/436)(第二次预览)
|
- [JEP 436: Virtual Threads(虚拟线程)](https://openjdk.org/jeps/436)(第二次预览)
|
||||||
- [JEP 437: Structured Concurrency(结构化并发)](https://openjdk.org/jeps/437)(第二次孵化)
|
- [JEP 437:Structured Concurrency(结构化并发)](https://openjdk.org/jeps/437)(第二次孵化)
|
||||||
- [JEP 432:向量 API(](https://openjdk.org/jeps/438)第五次孵化)
|
- [JEP 432:向量 API(](https://openjdk.org/jeps/438)第五次孵化)
|
||||||
|
|
||||||
## JEP 429:作用域值(第一次孵化)
|
## JEP 429:作用域值(第一次孵化)
|
||||||
|
|
||||||
@ -38,20 +38,109 @@ ScopedValue.where(V, <value>)
|
|||||||
|
|
||||||
作用域值允许在大型程序中的组件之间安全有效地共享数据,而无需求助于方法参数。
|
作用域值允许在大型程序中的组件之间安全有效地共享数据,而无需求助于方法参数。
|
||||||
|
|
||||||
关于作用域值的详细介绍,推荐阅读[作用域值常见问题解答](https://www.happycoders.eu/java/scoped-values/)。
|
关于作用域值的详细介绍,推荐阅读[作用域值常见问题解答](https://www.happycoders.eu/java/scoped-values/)这篇文章。
|
||||||
|
|
||||||
## JEP 432:记录模式(第二次预览)
|
## JEP 432:记录模式(第二次预览)
|
||||||
|
|
||||||
记录模式(Record Patterns) 可对 record 的值进行解构,可以嵌套记录模式和类型模式,实现强大的、声明性的和可组合的数据导航和处理形式。
|
记录模式(Record Patterns) 可对 record 的值进行解构,也就是更方便地从记录类(Record Class)中提取数据。并且,还可以嵌套记录模式和类型模式结合使用,以实现强大的、声明性的和可组合的数据导航和处理形式。
|
||||||
|
|
||||||
记录模式不能单独使用,而是要与 instanceof 或 switch 模式匹配一同使用。
|
记录模式不能单独使用,而是要与 instanceof 或 switch 模式匹配一同使用。
|
||||||
|
|
||||||
记录模式在 Java 19 进行了第一次预览, 由[JEP 405](https://openjdk.org/jeps/405)提出。JDK 20 中是第二次预览,由 [JEP 432](https://openjdk.org/jeps/432) 提出。这次的改进包括:
|
先以 instanceof 为例简单演示一下。
|
||||||
|
|
||||||
|
简单定义一个记录类:
|
||||||
|
|
||||||
|
```java
|
||||||
|
record Shape(String type, long unit){}
|
||||||
|
```
|
||||||
|
|
||||||
|
没有记录模式之前:
|
||||||
|
|
||||||
|
```java
|
||||||
|
Shape circle = new Shape("Circle", 10);
|
||||||
|
if (circle instanceof Shape shape) {
|
||||||
|
|
||||||
|
System.out.println("Area of " + shape.type() + " is : " + Math.PI * Math.pow(shape.unit(), 2));
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
有了记录模式之后:
|
||||||
|
|
||||||
|
```java
|
||||||
|
Shape circle = new Shape("Circle", 10);
|
||||||
|
if (circle instanceof Shape(String type, long unit)) {
|
||||||
|
System.out.println("Area of " + type + " is : " + Math.PI * Math.pow(unit, 2));
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
再看看记录模式与 switch 的配合使用。
|
||||||
|
|
||||||
|
定义一些类:
|
||||||
|
|
||||||
|
```java
|
||||||
|
interface Shape {}
|
||||||
|
record Circle(double radius) implements Shape { }
|
||||||
|
record Square(double side) implements Shape { }
|
||||||
|
record Rectangle(double length, double width) implements Shape { }
|
||||||
|
```
|
||||||
|
|
||||||
|
没有记录模式之前:
|
||||||
|
|
||||||
|
```java
|
||||||
|
Shape shape = new Circle(10);
|
||||||
|
switch (shape) {
|
||||||
|
case Circle c:
|
||||||
|
System.out.println("The shape is Circle with area: " + Math.PI * c.radius() * c.radius());
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Square s:
|
||||||
|
System.out.println("The shape is Square with area: " + s.side() * s.side());
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Rectangle r:
|
||||||
|
System.out.println("The shape is Rectangle with area: + " + r.length() * r.width());
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
System.out.println("Unknown Shape");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
有了记录模式之后:
|
||||||
|
|
||||||
|
```java
|
||||||
|
Shape shape = new Circle(10);
|
||||||
|
switch(shape) {
|
||||||
|
|
||||||
|
case Circle(double radius):
|
||||||
|
System.out.println("The shape is Circle with area: " + Math.PI * radius * radius);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Square(double side):
|
||||||
|
System.out.println("The shape is Square with area: " + side * side);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Rectangle(double length, double width):
|
||||||
|
System.out.println("The shape is Rectangle with area: + " + length * width);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
System.out.println("Unknown Shape");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
记录模式可以避免不必要的转换,使得代码更建简洁易读。而且,用了记录模式后不必再担心 `null` 或者 `NullPointerException`,代码更安全可靠。
|
||||||
|
|
||||||
|
记录模式在 Java 19 进行了第一次预览, 由 [JEP 405](https://openjdk.org/jeps/405) 提出。JDK 20 中是第二次预览,由 [JEP 432](https://openjdk.org/jeps/432) 提出。这次的改进包括:
|
||||||
|
|
||||||
- 添加对通用记录模式类型参数推断的支持,
|
- 添加对通用记录模式类型参数推断的支持,
|
||||||
- 添加对记录模式的支持以出现在增强语句的标题中`for`
|
- 添加对记录模式的支持以出现在增强语句的标题中`for`
|
||||||
- 删除对命名记录模式的支持。
|
- 删除对命名记录模式的支持。
|
||||||
|
|
||||||
|
**注意**:不要把记录模式和 [JDK16](./java16.md) 正式引入的记录类搞混了。
|
||||||
|
|
||||||
## JEP 433:switch 模式匹配(第四次预览)
|
## JEP 433:switch 模式匹配(第四次预览)
|
||||||
|
|
||||||
正如 `instanceof` 一样, `switch` 也紧跟着增加了类型匹配自动转换功能。
|
正如 `instanceof` 一样, `switch` 也紧跟着增加了类型匹配自动转换功能。
|
||||||
|
150
docs/java/new-features/java21.md
Normal file
150
docs/java/new-features/java21.md
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
---
|
||||||
|
title: Java 21 新特性概览(重要)
|
||||||
|
category: Java
|
||||||
|
tag:
|
||||||
|
- Java新特性
|
||||||
|
---
|
||||||
|
|
||||||
|
JDK 21 于 2023年9月19日 发布,这是一个非常重要的版本,里程碑式。
|
||||||
|
|
||||||
|
JDK21是 LTS(长期支持版),至此为止,目前有 JDK8、JDK11、JDK17和 JDK21这四个长期支持版了。
|
||||||
|
|
||||||
|
JDK 21 共有 15 个新特性:
|
||||||
|
|
||||||
|
- [JEP 430:String Templates(字符串模板)](https://openjdk.org/jeps/430)(预览)
|
||||||
|
- [JEP 431:Sequenced Collections(序列化集合)](https://openjdk.org/jeps/431)
|
||||||
|
|
||||||
|
- [JEP 439:Generational ZGC(分代ZGC)](https://openjdk.org/jeps/439)
|
||||||
|
|
||||||
|
- [JEP 440:Record Patterns(记录模式)](https://openjdk.org/jeps/440)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## JEP 430:字符串模板(预览)
|
||||||
|
|
||||||
|
String Templates(字符串模板) 目前仍然是 JDK 21 中的一个预览功能。
|
||||||
|
|
||||||
|
String Templates 提供了一种更简洁、更直观的方式来动态构建字符串。通过使用占位符`${}`,我们可以将变量的值直接嵌入到字符串中,而不需要手动处理。在运行时,Java 编译器会将这些占位符替换为实际的变量值。并且,表达式支持局部变量、静态/非静态字段甚至方法、计算结果等特性。
|
||||||
|
|
||||||
|
实际上,String Templates(字符串模板)再大多数编程语言中都存在:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
"Greetings {{ name }}!"; //Angular
|
||||||
|
`Greetings ${ name }!`; //Typescript
|
||||||
|
$"Greetings { name }!" //Visual basic
|
||||||
|
f"Greetings { name }!" //Python
|
||||||
|
```
|
||||||
|
|
||||||
|
Java 在没有 String Templates 之前,我们通常使用字符串拼接或格式化方法来构建字符串:
|
||||||
|
|
||||||
|
```java
|
||||||
|
//concatenation
|
||||||
|
message = "Greetings " + name + "!";
|
||||||
|
|
||||||
|
//String.format()
|
||||||
|
message = String.format("Greetings %s!", name); //concatenation
|
||||||
|
|
||||||
|
//MessageFormat
|
||||||
|
message = new MessageFormat("Greetings {0}!").format(name);
|
||||||
|
|
||||||
|
//StringBuilder
|
||||||
|
message = new StringBuilder().append("Greetings ").append(name).append("!").toString();
|
||||||
|
```
|
||||||
|
|
||||||
|
这些方法或多或少都存在一些缺点,比如难以阅读、冗长、复杂。
|
||||||
|
|
||||||
|
Java 使用 String Templates 进行字符串拼接,可以直接在字符串中嵌入表达式,而无需进行额外的处理:
|
||||||
|
|
||||||
|
```java
|
||||||
|
String message = STR."Greetings \{name}!";
|
||||||
|
```
|
||||||
|
|
||||||
|
在上面的模板表达式中:
|
||||||
|
|
||||||
|
- STR 是模板处理器。
|
||||||
|
- `\{name}`为表达式,运行时,这些表达式将被相应的变量值替换。
|
||||||
|
|
||||||
|
Java 目前支持三种模板处理器:
|
||||||
|
|
||||||
|
- STR:自动执行字符串插值,即将模板中的每个嵌入式表达式替换为其值(转换为字符串)。
|
||||||
|
- FMT:和STR类似,但是它还可以接受格式说明符,这些格式说明符出现在嵌入式表达式的左边,用来控制输出的样式
|
||||||
|
- RAW:不会像STR和FMT模板处理器那样自动处理字符串模板,而是返回一个 `StringTemplate` 对象,这个对象包含了模板中的文本和表达式的信息
|
||||||
|
|
||||||
|
```java
|
||||||
|
String name = "Lokesh";
|
||||||
|
|
||||||
|
//STR
|
||||||
|
String message = STR."Greetings \{name}.";
|
||||||
|
|
||||||
|
//FMT
|
||||||
|
String message = STR."Greetings %-12s\{name}.";
|
||||||
|
|
||||||
|
//RAW
|
||||||
|
StringTemplate st = RAW."Greetings \{name}.";
|
||||||
|
String message = STR.process(st);
|
||||||
|
```
|
||||||
|
|
||||||
|
除了JDK自带的三种模板处理器外,你还可以实现 `StringTemplate.Processor` 接口来创建自己的模板处理器。
|
||||||
|
|
||||||
|
我们可以使用局部变量、静态/非静态字段甚至方法作为嵌入表达式:
|
||||||
|
|
||||||
|
```java
|
||||||
|
//variable
|
||||||
|
message = STR."Greetings \{name}!";
|
||||||
|
|
||||||
|
//method
|
||||||
|
message = STR."Greetings \{getName()}!";
|
||||||
|
|
||||||
|
//field
|
||||||
|
message = STR."Greetings \{this.name}!";
|
||||||
|
```
|
||||||
|
|
||||||
|
还可以在表达式中执行计算并打印结果:
|
||||||
|
|
||||||
|
```java
|
||||||
|
int x = 10, y = 20;
|
||||||
|
String s = STR."\{x} + \{y} = \{x + y}"; //"10 + 20 = 30"
|
||||||
|
```
|
||||||
|
|
||||||
|
为了提高可读性,我们可以将嵌入的表达式分成多行:
|
||||||
|
|
||||||
|
```java
|
||||||
|
String time = STR."The current time is \{
|
||||||
|
//sample comment - current time in HH:mm:ss
|
||||||
|
DateTimeFormatter
|
||||||
|
.ofPattern("HH:mm:ss")
|
||||||
|
.format(LocalTime.now())
|
||||||
|
}.";
|
||||||
|
```
|
||||||
|
|
||||||
|
## JEP431:序列化集合
|
||||||
|
|
||||||
|
JDK 21引入了一种新的集合类型:**Sequenced Collections(序列化集合)**。
|
||||||
|
|
||||||
|
## JEP 439:分代ZGC
|
||||||
|
|
||||||
|
JDK21中对 ZGC 进行了功能扩展,增加了分代 GC 功能。不过,默认是关闭的,需要通过配置打开:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
// 启用分代ZGC
|
||||||
|
java -XX:+UseZGC -XX:+ZGenerational ...
|
||||||
|
```
|
||||||
|
|
||||||
|
在未来的版本中,官方会把 ZGenerational 设为默认值,即默认打开 ZGC 的分代 GC。在更晚的版本中,非分代ZGC就被移除。
|
||||||
|
|
||||||
|
> In a future release we intend to make Generational ZGC the default, at which point -XX:-ZGenerational will select non-generational ZGC. In an even later release we intend to remove non-generational ZGC, at which point the ZGenerational option will become obsolete.
|
||||||
|
>
|
||||||
|
> 在将来的版本中,我们打算将Generational ZGC作为默认选项,此时-XX:-ZGenerational将选择非分代ZGC。在更晚的版本中,我们打算移除非分代ZGC,此时ZGenerational选项将变得过时。
|
||||||
|
|
||||||
|
分代 ZGC 可以显著减少垃圾回收过程中的停顿时间,并提高应用程序的响应性能。这对于大型 Java 应用程序和高并发场景下的性能优化非常有价值。
|
||||||
|
|
||||||
|
## JEP 440:记录模式
|
||||||
|
|
||||||
|
记录模式在 Java 19 进行了第一次预览, 由 [JEP 405](https://openjdk.org/jeps/405) 提出。JDK 20 中是第二次预览,由 [JEP 432](https://openjdk.org/jeps/432) 提出。最终,记录模式在 JDK21 顺利转正。
|
||||||
|
|
||||||
|
[Java 20 新特性概览](./java20.md)已经详细介绍过记录模式,这里就不重复了。
|
||||||
|
|
||||||
|
## 参考
|
||||||
|
|
||||||
|
- Java 21 String Templates:<https://howtodoinjava.com/java/java-string-templates/>
|
||||||
|
-
|
Loading…
x
Reference in New Issue
Block a user