Java 12 和 13 主要引入了一些预览特性,其中最重要的是 Switch 表达式和文本块,这些特性在后续版本中得到了完善和正式化。
至于 Java 12 的 JVM 常量 API 和 Java 13 的动态 CDS 归档特性,企业开发中几乎用不到,不必学习。
- JVM 常量 API:提供了标准化的接口来描述和操作字节码中的常量池项,主要用于字节码操作工具和编译器开发,过于底层。
- 动态 CDS 归档:允许应用程序在运行时自动生成和更新类数据共享归档文件,无需预先手动创建。虽然能进一步优化启动性能,但配置复杂、收益有限,大多数企业应用没必要搞。
Java 12 新特性(2019年3月)
预览特性
【了解】Switch 表达式(预览)
Java 12 首次引入了 Switch 表达式作为预览特性,这是对传统 switch 语句的重大改进。
传统的 switch 语句存在一些问题:
// 传统 switch 语句的问题
String dayType;
switch (day) {
case MONDAY:
case TUESDAY:
case WEDNESDAY:
case THURSDAY:
case FRIDAY:
dayType = "工作日";
break; // 容易忘记 break,导致 fall-through
case SATURDAY:
case SUNDAY:
dayType = "周末";
break;
default:
dayType = "未知";
break;
}Java 12 的 Switch 表达式解决了这些问题:
// Java 12 预览版的 switch 表达式
String dayType = switch (day) {
case MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY -> "工作日";
case SATURDAY, SUNDAY -> "周末";
default -> "未知";
};主要改进:
- 箭头语法:使用
->避免 fall-through 问题 - 多标签:
case A, B, C ->支持多个条件 - 表达式:可以直接赋值给变量
- 简洁性:减少样板代码
注意:Java 12 中这是预览特性,需要特殊编译参数:
# 编译
javac --enable-preview --release 12 SwitchExample.java
# 运行
java --enable-preview SwitchExample正式特性
【了解】微基准测试套件
Java 12 引入了 JMH(Java Microbenchmark Harness)作为官方的微基准测试工具:
import org.openjdk.jmh.annotations.*;
import java.util.concurrent.TimeUnit;
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@State(Scope.Benchmark)
public class StringConcatBenchmark {
@Benchmark
public String stringConcat() {
return "Hello" + " " + "World";
}
@Benchmark
public String stringBuilder() {
return new StringBuilder()
.append("Hello")
.append(" ")
.append("World")
.toString();
}
}JMH 可以帮助开发者准确测量代码性能,避免 JIT 编译器优化带来的干扰。
【了解】默认 CDS 归档
Java 12 默认启用类数据共享(CDS)归档,JDK 安装时会预先创建一个包含常用核心类的归档文件:
# 查看默认 CDS 归档
java -Xshare:dump
# 使用 CDS 归档启动(默认启用)
java -Xshare:auto MyApp这可以减少应用启动时间和内存占用。
【了解】G1 垃圾收集器改进
Java 12 对 G1 垃圾收集器进行了两项重要改进:
1. 可中止混合收集
G1 可以在混合收集过程中中止,以满足暂停时间目标:
java -XX:+UseG1GC -XX:MaxGCPauseMillis=200 MyApp2. 及时返回未使用内存
G1 可以在空闲时将未使用的堆内存返回给操作系统:
java -XX:+UseG1GC -XX:G1PeriodicGCInterval=30000 MyApp实验特性
【了解】Shenandoah 垃圾收集器
Java 12 引入了 Shenandoah GC 作为实验特性,这是一个低延迟垃圾收集器:
# 启用 Shenandoah GC
java -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC MyAppShenandoah 的特点:
- 低延迟:暂停时间与堆大小无关
- 并发:大部分工作与应用线程并发执行
- 适用性:适合对延迟敏感的应用
Java 13 新特性(2019年9月)
预览特性
【了解】Switch 表达式(第二次预览)
Java 13 继续完善 Switch 表达式,主要改进是引入了 yield 关键字:
// Java 13 中的 switch 表达式
int score = switch (grade) {
case 'A', 'B' -> {
System.out.println("优秀成绩!");
yield 90; // 使用 yield 返回值
}
case 'C' -> 70;
case 'D' -> 60;
default -> {
System.out.println("需要努力!");
yield 0;
}
};yield 关键字用于在代码块中返回值,类似于 return,但专用于 switch 表达式。
【了解】文本块(预览)
Java 13 引入了文本块(Text Blocks)作为预览特性,解决多行字符串的编写问题:
// 传统的多行字符串
String html = "<html>\n" +
" <body>\n" +
" <h1>Hello World</h1>\n" +
" </body>\n" +
"</html>";
// Java 13 文本块(预览)
String html = """
<html>
<body>
<h1>Hello World</h1>
</body>
</html>
""";文本块的特点:
- 三引号语法:使用
"""包围 - 保持格式:保留原有的缩进和换行
- 转义简化:内部的引号不需要转义
特别适合编写:
- HTML/XML 内容
- SQL 查询语句
- JSON 字符串
- 正则表达式
正式特性
【了解】动态 CDS 归档
Java 13 支持在应用运行时动态创建 CDS 归档:
# 运行时生成 CDS 归档
java -XX:ArchiveClassesAtExit=myapp.jsa MyApp
# 使用生成的归档启动
java -XX:SharedArchiveFile=myapp.jsa MyApp动态 CDS 的优势:
- 自动化:无需手动分析类加载
- 精确性:只包含实际使用的类
- 便利性:适合复杂的应用场景
【了解】ZGC 内存管理改进
Java 13 改进了 ZGC 的内存管理,支持取消提交未使用的内存:
java -XX:+UnlockExperimentalVMOptions
-XX:+UseZGC
-XX:ZUncommitDelay=300
MyApp这个改进让 ZGC 可以:
- 在内存压力小时释放内存
- 提高系统整体内存利用率
- 适应动态的内存需求
【了解】重新实现传统套接字 API
Java 13 重新实现了 java.net.Socket 和 java.net.ServerSocket API:
// API 使用方式不变,但底层实现更现代化
ServerSocket serverSocket = new ServerSocket(8080);
Socket clientSocket = serverSocket.accept();
// 新实现的优势:
// 1. 更好的可维护性
// 2. 为 Project Loom(虚拟线程)做准备
// 3. 更好的调试支持这个改进对开发者来说是透明的,但为未来的虚拟线程等特性奠定了基础。
其他改进
【了解】String API 增强
Java 12-13 为 String 类添加了一些实用方法:
// Java 12 新增
String text = "Hello World";
// indent() - 调整缩进
String indented = text.indent(4);
System.out.println(indented); // " Hello World"
// transform() - 函数式转换
String result = text.transform(s -> s.toUpperCase())
.transform(s -> s.replace(" ", "_"));
System.out.println(result); // "HELLO_WORLD"
// Java 13 新增
// stripIndent() - 去除公共缩进
String multiLine = """
Line 1
Line 2
Line 3
""";
String stripped = multiLine.stripIndent();
// translateEscapes() - 处理转义字符
String escaped = "Hello\\nWorld\\t!";
String translated = escaped.translateEscapes();
System.out.println(translated); // Hello
// World !【了解】Files API 增强
Java 13 为 Files 类添加了 mismatch() 方法:
Path file1 = Paths.get("file1.txt");
Path file2 = Paths.get("file2.txt");
// 比较两个文件,返回第一个不同字节的位置
long mismatch = Files.mismatch(file1, file2);
if (mismatch == -1L) {
System.out.println("文件内容相同");
} else {
System.out.println("文件在位置 " + mismatch + " 开始不同");
}【了解】CompactNumberFormat
Java 12 引入了紧凑数字格式化:
import java.text.CompactNumberFormat;
import java.text.NumberFormat;
import java.util.Locale;
// 创建紧凑数字格式化器
NumberFormat cnf = CompactNumberFormat.getInstance(
Locale.CHINA, NumberFormat.Style.SHORT);
// 格式化大数字
System.out.println(cnf.format(1000)); // 1K
System.out.println(cnf.format(1000000)); // 100万
System.out.println(cnf.format(1000000000)); // 10亿
// 长格式
NumberFormat longFormat = CompactNumberFormat.getInstance(
Locale.CHINA, NumberFormat.Style.LONG);
System.out.println(longFormat.format(1000000)); // 100万总结
Java 12 和 13 主要是为后续重要特性做准备的版本。Switch 表达式和文本块虽然还是预览特性,但已经展现出了巨大的潜力,大大提升了代码的可读性和编写效率。
这两个版本的 GC 改进也很重要,特别是 Shenandoah 和 ZGC 的引入,为低延迟应用提供了更多选择。虽然大部分特性在当时还不够成熟,但为 Java 14-15 的正式特性奠定了基础。