Skip to content
<

Java 12 和 13 主要引入了⁢一些预览特性,其中最重要⁡的是 Switch 表达⁡式和文本块,这些特性在后续版本中得到了完善和正式化。

至于 Java 12 的 JVM ⁢常量 API 和 Ja⁡va 13 的动态 C⁡DS 归档特性,企业开发中几乎用不到,不必学习。

  • JVM 常量 API:提供了标准化的接口来描述和操作字节码中的常量池项,主要用于字节码操作工具和编译器开发,过于底层。
  • 动态 CDS 归档:允许应用程序在运行时自动生成和更新类数据共享归档文件,无需预先手动创建。虽然能进一步优化启动性能,但配置复杂、收益有限,大多数企业应用没必要搞。

Java 12 新特性(2019年3月)

预览特性

【了解】Switch 表达式(预览)

Java 12 首次引入了 ⁢Switch 表达⁡式作为预览特性,这⁡是对传统 switch 语句的重大改进。

传统的 switch 语句存在一些问题:

java
// 传统 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
// 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 中这是预览特⁢性,需要特殊编译参数:⁡           ⁡

bash
# 编译
javac --enable-preview --release 12 SwitchExample.java

# 运行
java --enable-preview SwitchExample

正式特性

【了解】微基准测试套件

Java 12 引入了 JMH⁢(Java Micr⁡obenchmark⁡ Harness)作为官方的微基准测试工具:

java
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 安装时⁡会预先创建一个包含常用核心类的归档文件:

bash
# 查看默认 CDS 归档
java -Xshare:dump

# 使用 CDS 归档启动(默认启用)
java -Xshare:auto MyApp

这可以减少应用启动时间和内存占用。

【了解】G1 垃圾收集器改进

Java 12 对 G1 垃圾收集器进行了两项重要改进:

1. 可中止混合收集

G1 可以在混合收集过程中中止,以满足暂停时间目标:

bash
java -XX:+UseG1GC -XX:MaxGCPauseMillis=200 MyApp

2. 及时返回未使用内存

G1 可以在空闲时将未使用的堆内存返回给操作系统:

bash
java -XX:+UseG1GC -XX:G1PeriodicGCInterval=30000 MyApp

实验特性

【了解】Shenandoah 垃圾收集器

Java 12 引入了 Sh⁢enandoah ⁡GC 作为实验特性⁡,这是一个低延迟垃圾收集器:

bash
# 启用 Shenandoah GC
java -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC MyApp

Shenandoah 的特点:

  • 低延迟:暂停时间与堆大小无关
  • 并发:大部分工作与应用线程并发执行
  • 适用性:适合对延迟敏感的应用

Java 13 新特性(2019年9月)

预览特性

【了解】Switch 表达式(第二次预览)

Java 13 继续完善 Switch 表达式,主要改进是引入了 yield 关键字:

java
// 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 Blo⁡cks)作为预览特⁡性,解决多行字符串的编写问题:

java
// 传统的多行字符串
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 归档:

bash
# 运行时生成 CDS 归档
java -XX:ArchiveClassesAtExit=myapp.jsa MyApp

# 使用生成的归档启动
java -XX:SharedArchiveFile=myapp.jsa MyApp

动态 CDS 的优势:

  • 自动化:无需手动分析类加载
  • 精确性:只包含实际使用的类
  • 便利性:适合复杂的应用场景

【了解】ZGC 内存管理改进

Java 13 改进了 ZG⁢C 的内存管理,支⁡持取消提交未使用的⁡内存:

bash
java -XX:+UnlockExperimentalVMOptions 
     -XX:+UseZGC 
     -XX:ZUncommitDelay=300 
     MyApp

这个改进让 ZGC 可以: ⁢         ⁡         ⁡

  • 在内存压力小时释放内存
  • 提高系统整体内存利用率
  • 适应动态的内存需求

【了解】重新实现传统套接字 API

Java 13 重新实现了 java.net.Socketjava.net.ServerSocket API:

java
// API 使用方式不变,但底层实现更现代化
ServerSocket serverSocket = new ServerSocket(8080);
Socket clientSocket = serverSocket.accept();

// 新实现的优势:
// 1. 更好的可维护性
// 2. 为 Project Loom(虚拟线程)做准备
// 3. 更好的调试支持

这个改进对开发者来说是透明的,但为未⁢来的虚拟线程等特性奠定了⁡基础。

其他改进

【了解】String API 增强

Java 12-13 为 S⁢tring 类添加⁡了一些实用方法:

java
// 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() 方法:

java
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 引入了紧凑数字格式化:

java
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 改进也很重要,特别是 Shenan⁢doah 和 ZGC 的引入,为低延⁡迟应用提供了更多选择。虽然大部分特性⁡在当时还不够成熟,但为 Java 14-15 的正式特性奠定了基础。