Java 12 核心特性解析
Java 12于2019年3月发布,是一个非LTS版本,引入了一些实验性特性和性能改进。
Switch表达式(预览)
特性概述
Java 12首次引入了Switch表达式作为预览特性,这是对传统switch语句的增强,使其可以作为表达式使用,并提供了更简洁的语法。
技术细节
Switch表达式的主要改进:
- 可以作为表达式返回值
- 使用
->
箭头语法代替传统的case:
和break;
- 不会出现传统switch语句中的fall-through问题
- 编译器会检查是否覆盖了所有可能的情况
// 传统switch语句
String dayType;
switch (day) {
case MONDAY:
case TUESDAY:
case WEDNESDAY:
case THURSDAY:
case FRIDAY:
dayType = "工作日";
break;
case SATURDAY:
case SUNDAY:
dayType = "周末";
break;
default:
dayType = "未知";
}
// Java 12 switch表达式(使用箭头语法)
String dayType = switch (day) {
case MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY -> "工作日";
case SATURDAY, SUNDAY -> "周末";
default -> "未知";
};
需要注意的是,在Java 12中,这是一个预览特性,需要使用--enable-preview
标志启用。
应用场景
- 枚举类型处理
// 处理枚举类型
enum Status { ACTIVE, INACTIVE, PENDING, DELETED }
String message = switch (status) {
case ACTIVE -> "账户已激活";
case INACTIVE -> "账户未激活";
case PENDING -> "账户待审核";
case DELETED -> "账户已删除";
};
- 复杂条件判断
// 替代复杂的if-else链
int numLetters = switch (day) {
case MONDAY, FRIDAY, SUNDAY -> 6;
case TUESDAY -> 7;
case THURSDAY, SATURDAY -> 8;
case WEDNESDAY -> 9;
default -> throw new IllegalStateException("无效的日期: " + day);
};
Shenandoah GC(实验性)
特性概述
Java 12引入了Shenandoah垃圾收集器作为实验性特性,它是一种低停顿时间的垃圾收集器,旨在减少GC暂停时间。
技术细节
Shenandoah GC的主要特点:
- 与应用程序并发执行,包括并发压缩
- 停顿时间与堆大小无关,无论堆是200MB还是200GB
- 使用Brooks转发指针和读屏障技术
- 适用于需要低延迟的应用程序
# 启用Shenandoah GC
java -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC MyApplication
应用场景
- 交互式应用
# 为交互式应用配置Shenandoah
java -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=adaptive InteractiveApp
- 大内存服务器应用
# 为大内存应用配置Shenandoah
java -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=compact -Xms16g -Xmx16g BigDataApp
微基准测试套件
特性概述
Java 12添加了一套基于JMH(Java Microbenchmark Harness)的微基准测试套件,用于测试和比较JDK的性能。
技术细节
微基准测试套件位于jdk/test/micro
目录下,可以用来测试JDK各个组件的性能:
- 字符串操作
- 集合框架
- 正则表达式
- 流处理
- 等等
# 运行微基准测试
cd jdk/test/micro
make run-micro-benchmarks
应用场景
- 性能调优
// 使用JMH进行基准测试
@Benchmark
public void testStringConcatenation() {
String result = "Hello" + ", " + "World!";
}
- 比较算法实现
// 比较不同排序算法
@Benchmark
public void testQuickSort(Blackhole bh) {
int[] array = generateRandomArray(1000);
Arrays.sort(array);
bh.consume(array);
}
@Benchmark
public void testCustomSort(Blackhole bh) {
int[] array = generateRandomArray(1000);
customSort(array);
bh.consume(array);
}
紧凑的数字格式
特性概述
Java 12增强了NumberFormat
类,添加了紧凑的数字格式化支持,可以将大数字以更易读的形式显示。
技术细节
紧凑数字格式有两种样式:
- 短样式:如"1K"、“1M”、“1B”
- 长样式:如"1千"、“1百万”、“1十亿”
// 短样式
NumberFormat fmt = NumberFormat.getCompactNumberInstance(Locale.CHINA, NumberFormat.Style.SHORT);
System.out.println(fmt.format(1000)); // 1千
System.out.println(fmt.format(1000000)); // 1百万
System.out.println(fmt.format(1000000000)); // 10亿
// 长样式
NumberFormat fmtLong = NumberFormat.getCompactNumberInstance(Locale.CHINA, NumberFormat.Style.LONG);
System.out.println(fmtLong.format(1000)); // 1千
System.out.println(fmtLong.format(1000000)); // 1百万
System.out.println(fmtLong.format(1000000000)); // 10亿
// 自定义格式
NumberFormat fmt = NumberFormat.getCompactNumberInstance(Locale.US, NumberFormat.Style.SHORT);
fmt.setMaximumFractionDigits(1);
System.out.println(fmt.format(1234)); // 1.2K
System.out.println(fmt.format(1234567)); // 1.2M
应用场景
- 用户界面显示
// 显示社交媒体数据
long viewCount = 1234567;
NumberFormat fmt = NumberFormat.getCompactNumberInstance(Locale.CHINA, NumberFormat.Style.SHORT);
System.out.println("视频播放量: " + fmt.format(viewCount)); // 视频播放量: 123万
- 数据可视化
// 图表数据标签
long[] values = {1200, 45000, 1250000, 98000000};
NumberFormat fmt = NumberFormat.getCompactNumberInstance(Locale.CHINA, NumberFormat.Style.SHORT);
for (long value : values) {
System.out.println(fmt.format(value));
}
// 输出: 1.2千, 4.5万, 125万, 9800万
文件比较API
特性概述
Java 12引入了Files.mismatch()
方法,用于比较两个文件的内容,并返回第一个不匹配的位置。
技术细节
mismatch()
方法返回两个文件内容第一个不匹配字节的位置,如果文件内容相同则返回-1。
// 比较两个文件
Path path1 = Path.of("file1.txt");
Path path2 = Path.of("file2.txt");
long mismatchPosition = Files.mismatch(path1, path2);
if (mismatchPosition == -1) {
System.out.println("文件内容完全相同");
} else {
System.out.println("文件在位置 " + mismatchPosition + " 处开始不同");
}
应用场景
- 文件完整性检查
// 检查文件是否被修改
Path original = Path.of("original.dat");
Path backup = Path.of("backup.dat");
if (Files.mismatch(original, backup) != -1) {
System.out.println("警告:文件已被修改!");
backupFile(original);
}
- 二进制文件比较
// 比较二进制文件
Path binary1 = Path.of("program1.bin");
Path binary2 = Path.of("program2.bin");
long diff = Files.mismatch(binary1, binary2);
if (diff != -1) {
byte[] content1 = Files.readAllBytes(binary1);
byte[] content2 = Files.readAllBytes(binary2);
System.out.printf("位置 %d: %02X vs %02X%n", diff, content1[(int)diff], content2[(int)diff]);
}
其他重要特性
默认CDS归档文件
Java 12在安装过程中生成默认的类数据共享(CDS)归档文件,提高了应用启动性能。
改进G1垃圾收集器
Java 12对G1垃圾收集器进行了多项改进:
- 可中止的混合收集集合
- 立即返回未使用的已提交内存
# 使用改进的G1收集器
java -XX:+UseG1GC -XX:G1HeapRegionSize=16m MyApplication
改进Aarch64实现
Java 12改进了对ARM 64位架构(Aarch64)的支持,包括:
- 实现了Aarch64上的默认CDS
- 改进了Aarch64上的字符串和数组内在函数
JVM常量API
Java 12增强了JVM常量API,为Java语言和JVM上的其他语言提供了更丰富的符号引用信息。
// 使用常量API
MethodHandles.Lookup lookup = MethodHandles.lookup();
VarHandle vh = lookup.findVarHandle(MyClass.class, "myField", int.class);
移除了的功能
Java 12移除了以下功能:
- 移除了
com.sun.awt.SecurityWarning
类 - 移除了
javac
的-source
和-target
选项对6和1.6的支持 - 移除了
GTE CyberTrust Global Root
证书