JavaGuide/docs/java/new-features/java12-13.md

299 lines
10 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
title: Java 12 & 13 新特性概览
category: Java
tag:
- Java新特性
---
## Java12
### String 增强
Java 12 增加了两个的字符串处理方法,如以下所示。
`indent()` 方法可以实现字符串缩进。
```java
String text = "Java";
// 缩进 4 格
text = text.indent(4);
System.out.println(text);
text = text.indent(-10);
System.out.println(text);
```
输出:
```plain
Java
Java
```
`transform()` 方法可以用来转变指定字符串。
```java
String result = "foo".transform(input -> input + " bar");
System.out.println(result); // foo bar
```
### Files 增强(文件比较)
Java 12 添加了以下方法来比较两个文件:
```java
public static long mismatch(Path path, Path path2) throws IOException
```
`mismatch()` 方法用于比较两个文件,并返回第一个不匹配字符的位置,如果文件相同则返回 -1L。
代码示例(两个文件内容相同的情况):
```java
Path filePath1 = Files.createTempFile("file1", ".txt");
Path filePath2 = Files.createTempFile("file2", ".txt");
Files.writeString(filePath1, "Java 12 Article");
Files.writeString(filePath2, "Java 12 Article");
long mismatch = Files.mismatch(filePath1, filePath2);
assertEquals(-1, mismatch);
```
代码示例(两个文件内容不相同的情况):
```java
Path filePath3 = Files.createTempFile("file3", ".txt");
Path filePath4 = Files.createTempFile("file4", ".txt");
Files.writeString(filePath3, "Java 12 Article");
Files.writeString(filePath4, "Java 12 Tutorial");
long mismatch = Files.mismatch(filePath3, filePath4);
assertEquals(8, mismatch);
```
### 数字格式化工具类
`NumberFormat` 新增了对复杂的数字进行格式化的支持
```java
NumberFormat fmt = NumberFormat.getCompactNumberInstance(Locale.US, NumberFormat.Style.SHORT);
String result = fmt.format(1000);
System.out.println(result);
```
输出:
```plain
1K
```
### Shenandoah GC
Redhat 主导开发的 Pauseless GC 实现,主要目标是 99.9% 的暂停小于 10ms暂停与堆大小无关等
和 Java11 开源的 ZGC 相比(需要升级到 JDK11 才能使用Shenandoah GC 有稳定的 JDK8u 版本,在 Java8 占据主要市场份额的今天有更大的可落地性。
### G1 收集器优化
Java12 为默认的垃圾收集器 G1 带来了两项更新:
- **可中止的混合收集集合**JEP344 的实现为了达到用户提供的停顿时间目标JEP 344 通过把要被回收的区域集(混合收集集合)拆分为强制和可选部分,使 G1 垃圾回收器能中止垃圾回收过程。 G1 可以中止可选部分的回收以达到停顿时间目标
- **及时返回未使用的已分配内存**JEP346 的实现,增强 G1 GC以便在空闲时自动将 Java 堆内存返回给操作系统
### 预览新特性
作为预览特性加入,需要在`javac`编译和`java`运行时增加参数`--enable-preview` 。
#### 增强 Switch
传统的 `switch` 语法存在容易漏写 `break` 的问题,而且从代码整洁性层面来看,多个 break 本质也是一种重复。
Java12 增强了 `switch` 表达式,使用类似 lambda 语法条件匹配成功后的执行块,不需要多写 break 。
```java
switch (day) {
case MONDAY, FRIDAY, SUNDAY -> System.out.println(6);
case TUESDAY -> System.out.println(7);
case THURSDAY, SATURDAY -> System.out.println(8);
case WEDNESDAY -> System.out.println(9);
}
```
#### instanceof 模式匹配
`instanceof` 主要在类型强转前探测对象的具体类型。
之前的版本中,我们需要显示地对对象进行类型转换。
```java
Object obj = "我是字符串";
if(obj instanceof String){
String str = (String) obj;
System.out.println(str);
}
```
新版的 `instanceof` 可以在判断是否属于具体的类型同时完成转换。
```java
Object obj = "我是字符串";
if(obj instanceof String str){
System.out.println(str);
}
```
## Java13
### 增强 ZGC(释放未使用内存)
在 Java 11 中实验性引入的 ZGC 在实际的使用中存在未能主动将未使用的内存释放给操作系统的问题。
ZGC 堆由一组称为 ZPages 的堆区域组成。在 GC 周期中清空 ZPages 区域时,它们将被释放并返回到页面缓存 **ZPageCache** 中,此缓存中的 ZPages 按最近最少使用LRU的顺序并按照大小进行组织。
在 Java 13 中ZGC 将向操作系统返回被标识为长时间未使用的页面,这样它们将可以被其他进程重用。
### SocketAPI 重构
Java Socket API 终于迎来了重大更新!
Java 13 将 Socket API 的底层进行了重写, `NioSocketImpl` 是对 `PlainSocketImpl` 的直接替代,它使用 `java.util.concurrent` 包下的锁而不是同步方法。如果要使用旧实现,请使用 `-Djdk.net.usePlainSocketImpl=true`
并且,在 Java 13 中是默认使用新的 Socket 实现。
```java
public final class NioSocketImpl extends SocketImpl implements PlatformSocketImpl {
}
```
### FileSystems
`FileSystems` 类中添加了以下三种新方法,以便更容易地使用将文件内容视为文件系统的文件系统提供程序:
- `newFileSystem(Path)`
- `newFileSystem(Path, Map<String, ?>)`
- `newFileSystem(Path, Map<String, ?>, ClassLoader)`
### 动态 CDS 存档
Java 13 中对 Java 10 中引入的应用程序类数据共享(AppCDS)进行了进一步的简化、改进和扩展,即:**允许在 Java 应用程序执行结束时动态进行类归档**,具体能够被归档的类包括所有已被加载,但不属于默认基层 CDS 的应用程序类和引用类库中的类。
这提高了应用程序类数据共享([AppCDS](https://openjdk.java.net/jeps/310))的可用性。无需用户进行试运行来为每个应用程序创建类列表。
```bash
java -XX:ArchiveClassesAtExit=my_app_cds.jsa -cp my_app.jar
java -XX:SharedArchiveFile=my_app_cds.jsa -cp my_app.jar
```
### 预览新特性
#### 文本块
解决 Java 定义多行字符串时只能通过换行转义或者换行连接符来变通支持的问题,引入**三重双引号**来定义多行文本。
Java 13 支持两个 `"""` 符号中间的任何内容都会被解释为字符串的一部分,包括换行符。
未支持文本块之前的 HTML 写法:
```java
String json ="{\n" +
" \"name\":\"mkyong\",\n" +
" \"age\":38\n" +
"}\n";
```
支持文本块之后的 HTML 写法:
```java
String json = """
{
"name":"mkyong",
"age":38
}
""";
```
未支持文本块之前的 SQL 写法:
```sql
String query = "SELECT `EMP_ID`, `LAST_NAME` FROM `EMPLOYEE_TB`\n" +
"WHERE `CITY` = 'INDIANAPOLIS'\n" +
"ORDER BY `EMP_ID`, `LAST_NAME`;\n";
```
支持文本块之后的 SQL 写法:
```sql
String query = """
SELECT `EMP_ID`, `LAST_NAME` FROM `EMPLOYEE_TB`
WHERE `CITY` = 'INDIANAPOLIS'
ORDER BY `EMP_ID`, `LAST_NAME`;
""";
```
另外,`String` 类新增加了 3 个新的方法来操作文本块:
- `formatted(Object... args)`:它类似于 `String` 的`format()`方法。添加它是为了支持文本块的格式设置。
- `stripIndent()`:用于去除文本块中每一行开头和结尾的空格。
- `translateEscapes()`:转义序列如 _“\\\t”_ 转换为 _“\t”_
由于文本块是一项预览功能,可以在未来版本中删除,因此这些新方法被标记为弃用。
```java
@Deprecated(forRemoval=true, since="13")
public String stripIndent() {
}
@Deprecated(forRemoval=true, since="13")
public String formatted(Object... args) {
}
@Deprecated(forRemoval=true, since="13")
public String translateEscapes() {
}
```
#### 增强 Switch(引入 yield 关键字到 Switch 中)
`Switch` 表达式中就多了一个关键字用于跳出 `Switch` 块的关键字 `yield`,主要用于返回一个值
`yield``return` 的区别在于:`return` 会直接跳出当前循环或者方法,而 `yield` 只会跳出当前 `Switch` 块,同时在使用 `yield` 时,需要有 `default` 条件
```java
private static String descLanguage(String name) {
return switch (name) {
case "Java": yield "object-oriented, platform independent and secured";
case "Ruby": yield "a programmer's best friend";
default: yield name +" is a good language";
};
}
```
## 补充
### 关于预览特性
先贴一段 oracle 官网原文:`This is a preview feature, which is a feature whose design, specification, and implementation are complete, but is not permanent, which means that the feature may exist in a different form or not at all in future JDK releases. To compile and run code that contains preview features, you must specify additional command-line options.`
这是一个预览功能,该功能的设计,规格和实现是完整的,但不是永久性的,这意味着该功能可能以其他形式存在或在将来的 JDK 版本中根本不存在。 要编译和运行包含预览功能的代码,必须指定其他命令行选项。
就以`switch`的增强为例子,从 Java12 中推出,到 Java13 中将继续增强,直到 Java14 才正式转正进入 JDK 可以放心使用,不用考虑后续 JDK 版本对其的改动或修改
一方面可以看出 JDK 作为标准平台在增加新特性的严谨态度,另一方面个人认为是对于预览特性应该采取审慎使用的态度。特性的设计和实现容易,但是其实际价值依然需要在使用中去验证
### JVM 虚拟机优化
每次 Java 版本的发布都伴随着对 JVM 虚拟机的优化,包括对现有垃圾回收算法的改进,引入新的垃圾回收算法,移除老旧的不再适用于今天的垃圾回收算法等
整体优化的方向是**高效,低时延的垃圾回收表现**
对于日常的应用开发者可能比较关注新的语法特性,但是从一个公司角度来说,在考虑是否升级 Java 平台时更加考虑的是**JVM 运行时的提升**
## 参考
- JDK Project Overview<https://openjdk.java.net/projects/jdk/>
- Oracle Java12 ReleaseNote<https://www.oracle.com/java/technologies/javase/12all-relnotes.htm>
- What is new in Java 12<https://mkyong.com/java/what-is-new-in-java-12/>
- Oracle Java13 ReleaseNote <https://www.oracle.com/technetwork/java/javase/13all-relnotes-5461743.html#NewFeature>
- New Java13 Features <https://www.baeldung.com/java-13-new-features>
- Java13 新特性概述 <https://www.ibm.com/developerworks/cn/java/the-new-features-of-Java-13/index.html>
<!-- @include: @article-footer.snippet.md -->