1. 简介
在本篇文章中,我们将快速、高层次地介绍 Java 12 中引入的一些新特性。如果你想要完整的特性列表,可以参考 官方文档。
2. 语言层面的新特性
Java 12 在语言层面引入了多个值得关注的更新。下面我们将重点介绍几个最有趣的功能,并结合代码示例来加深理解。
2.1. String 类新增方法
Java 12 为 String
类增加了两个实用方法:indent
和 transform
。
✅ indent 方法
该方法用于调整字符串每一行的缩进。参数为整数:
- 如果是正数,则在每行前添加对应数量的空格;
- 如果是负数,则从每行开头移除对应数量的空格(如果不够则全部移除);
来看一个例子:
String text = "Hello Baeldung!\nThis is Java 12 article.";
text = text.indent(4);
System.out.println(text);
text = text.indent(-10);
System.out.println(text);
输出结果如下:
Hello Baeldung!
This is Java 12 article.
Hello Baeldung!
This is Java 12 article.
⚠️ 注意:即使传入 -10
这样的值,也不会影响非空白字符。
✅ transform 方法
这个方法接受一个 Function
参数,将函数应用到当前字符串并返回处理后的结果。
举个例子,我们将字符串反转:
@Test
public void givenString_thenRevertValue() {
String text = "Baeldung";
String transformed = text.transform(value ->
new StringBuilder(value).reverse().toString()
);
assertEquals("gnudleaB", transformed);
}
2.2. File::mismatch 方法
Java 12 在 Files
工具类中新增了一个静态方法 mismatch(Path, Path)
,用于比较两个文件内容,找出第一个不匹配的字节位置。
返回值说明:
- 返回
-1L
表示两个文件完全相同; - 否则返回第一个不同字节的位置索引(从 0 开始);
示例一:两个相同的文件
@Test
public void givenIdenticalFiles_thenShouldNotFindMismatch() {
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);
}
示例二:两个内容不同的文件
@Test
public void givenDifferentFiles_thenShouldFindMismatch() {
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);
}
2.3. Teeing Collector
Java 12 新增了一个名为 teeing
的收集器(Collector),它允许你同时使用两个下游收集器对流进行处理,再将它们的结果合并。
构造方式如下:
Collector<T, ?, R> teeing(Collector<? super T, ?, R1> downstream1,
Collector<? super T, ?, R2> downstream2, BiFunction<? super R1, ? super R2, R> merger)
示例:计算一组数字的平均值:
@Test
public void givenSetOfNumbers_thenCalculateAverage() {
double mean = Stream.of(1, 2, 3, 4, 5)
.collect(Collectors.teeing(Collectors.summingDouble(i -> i),
Collectors.counting(), (sum, count) -> sum / count));
assertEquals(3.0, mean);
}
2.4. 紧凑数字格式化(Compact Number Formatting)
Java 12 引入了紧凑数字格式器 CompactNumberFormat
,可以根据本地化规则将数字以更简洁的形式展示,例如“10K”或“10 thousand”。
获取方式:
NumberFormat.getCompactNumberInstance(Locale locale, NumberFormat.Style formatStyle)
支持两种风格:
SHORT
:如 “10K”LONG
:如 “10 thousand”
示例:
@Test
public void givenNumber_thenCompactValues() {
NumberFormat likesShort =
NumberFormat.getCompactNumberInstance(new Locale("en", "US"), NumberFormat.Style.SHORT);
likesShort.setMaximumFractionDigits(2);
assertEquals("2.59K", likesShort.format(2592));
NumberFormat likesLong =
NumberFormat.getCompactNumberInstance(new Locale("en", "US"), NumberFormat.Style.LONG);
likesLong.setMaximumFractionDigits(2);
assertEquals("2.59 thousand", likesLong.format(2592));
}
3. 预览功能(Preview Features)
部分新功能目前仅作为预览提供。要启用这些功能,需要在编译时加上特定参数:
javac -Xlint:preview --enable-preview -source 12 src/main/java/File.java
3.1. Switch 表达式(Preview)
这是 Java 12 中最受关注的更新之一,让 switch 更加简洁和强大。
旧写法:
DayOfWeek dayOfWeek = LocalDate.now().getDayOfWeek();
String typeOfDay = "";
switch (dayOfWeek) {
case MONDAY:
case TUESDAY:
case WEDNESDAY:
case THURSDAY:
case FRIDAY:
typeOfDay = "Working Day";
break;
case SATURDAY:
case SUNDAY:
typeOfDay = "Day Off";
}
新写法(Switch Expressions):
typeOfDay = switch (dayOfWeek) {
case MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY -> "Working Day";
case SATURDAY, SUNDAY -> "Day Off";
};
✅ 优势:
- 更加简洁;
- 自动避免 fall-through;
- 支持直接赋值;
- 可以执行无返回值的语句块;
复杂逻辑可用大括号包裹:
case MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY -> {
// more logic
System.out.println("Working Day")
}
⚠️ 注意:你可以选择继续使用传统语法,Java 12 的 Switch Expressions 是增强而非替代。
3.2. instanceof 的模式匹配(Preview)
以往在使用 instanceof
判断类型后,还需要手动强转对象才能访问其方法:
Object obj = "Hello World!";
if (obj instanceof String) {
String s = (String) obj;
int length = s.length();
}
现在可以直接在条件中声明变量:
if (obj instanceof String s) {
int length = s.length();
}
编译器会自动完成类型转换。
4. JVM 层面的改进
Java 12 也在 JVM 层面带来了多项优化。
4.1. Shenandoah GC:低延迟垃圾回收器
Shenandoah 是一个实验性的 GC 算法,目标是显著降低 GC 暂停时间。它通过与运行中的 Java 线程并发执行清理工作,使得暂停时间不再受堆大小影响。
⚠️ 注意:此功能在 Java 12 中默认未启用,自 Java 15 起成为主线版本的一部分。
4.2. 微基准测试套件(Microbenchmark Suite)
Java 12 引入了一套约 100 个微基准测试用例,方便开发者持续监控 JVM 性能,也适用于开发新的微基准测试。
4.3. 默认启用 CDS(Class Data Sharing)
CDS 功能可加快 JVM 启动速度并减少内存占用。Java 12 开始默认启用了 CDS 归档。
如果想禁用,可以使用如下参数:
java -Xshare:off HelloWorld.java
⚠️ 注意:关闭 CDS 可能会导致启动时间变长。
5. 结语
本文介绍了 Java 12 中的主要新特性和改进点。当然还有很多其他细节变化,感兴趣的读者可以查阅官方文档。完整示例代码可以在 GitHub 仓库 获取。