1. 什么是 Project Amber

Project Amber 是由 Java 和 OpenJDK 开发团队发起的一个长期项目,目标是为 JDK 带来一些小而精的改进,让 Java 开发体验更加舒适。该项目自 2017 年启动以来,已经在 Java 10、11 中交付了部分特性,其余功能也陆续在 Java 12 及后续版本中落地。

这些改进都是以 JEP(JDK Enhancement Proposal) 的形式提出的。

2. 已交付的更新

截至目前,Project Amber 已成功将一些特性集成进 JDK 的正式版本中,包括 JEP-286JEP-323

2.1. 局部变量类型推断

Java 7 引入了 Diamond Operator 来简化泛型语法:

List<String> strings = new ArrayList<String>(); // Java 6
List<String> strings = new ArrayList<>();       // Java 7

Java 10 通过 JEP-286 实现了局部变量类型推断,开发者可以用 var 关键字代替显式类型声明,编译器会自动推断类型:

var strings = new ArrayList<String>();

上面这行代码中,strings 的类型会被推断为 ArrayList<String>,无需重复声明。

适用场景:适用于任何局部变量定义,包括方法返回值、表达式等。

不适用场景

  • 没有初始化值:var unknownType;
  • 显式赋值为 nullvar nullType = null;
  • Lambda 表达式(无类型信息):var lambdaType = () -> {};

⚠️ 特殊情况:如果 null 是某个方法的返回值,是可以推断出类型的:

Optional<String> name = Optional.empty();
var nullName = name.orElse(null); // 推断为 String

💡 var 是一个特殊类型名,不是关键字,因此可以作为变量名使用,但强烈建议不要这么做,容易引起歧义。

✅ 局部变量也可以加上修饰符,如 finalsynchronized 等:

final var name = "Baeldung";

2.2. Lambda 参数的局部变量类型推断

Java 10 中,Lambda 参数要么全写类型,要么全省略:

names.stream()
  .filter(String name -> name.length() > 5)
  .map(name -> name.toUpperCase());

Java 11 支持在 Lambda 参数中使用 var,保持一致性:

names.stream()
  .filter(var name -> name.length() > 5)
  .map(var name -> name.toUpperCase());

⚠️ 规则限制

  • Lambda 参数要么全用 var,要么全不用。
  • 不允许混用 var 和显式类型。
// ✅ 合法
numbers.stream().reduce(0, (var a, var b) -> a + b);

// ❌ 非法
numbers.stream().reduce(0, (var a, b) -> a + b);
numbers.stream().reduce(0, (var a, int b) -> a + b);

3. 即将发布的更新

除了已发布的特性,JDK 12 中还引入了 JEP-325

3.1. Switch 表达式

传统 switch 语句容易出错(比如忘记 break),而 JEP-325 引入了更简洁的 switch 表达式语法,类似 Kotlin 的 when 或 Scala 的 match

switch (month) {
    case FEBRUARY -> System.out.println(28);
    case APRIL, JUNE, SEPTEMBER, NOVEMBER -> System.out.println(30);
    default -> System.out.println(31);
}

优点

  • 自动 break,不会 fallthrough。
  • 右侧可以是表达式、代码块或 throw 语句。
  • 支持逗号分隔多个 case。
switch (month) {
    case FEBRUARY -> {
        int days = 28;
    }
    case APRIL -> {
        int days = 30;
    }
}

作为表达式使用

final var days = switch (month) {
    case FEBRUARY -> 28;
    case APRIL, JUNE, SEPTEMBER, NOVEMBER -> 30;
    default -> 31;
};

4. 未来规划中的特性

以下特性仍在提案阶段,尚未排期发布。

4.1. 原始字符串字面量(Raw String Literals)

目前 Java 字符串必须用双引号包裹,转义字符麻烦。JEP-326 提议引入反引号包裹的原始字符串:

// 传统写法
"C:\\Dev\\file.txt"
"\\d+\\.\\d\\d"
"Hello\nWorld"

// 新写法
`C:\Dev\file.txt`
`\d+\.\d\d`
`Hello
World`

✅ 反引号也可以嵌套使用:

``This string allows a single "`" because it's wrapped in two backticks``

4.2. Lambda 剩余优化(Lambda Leftovers)

JEP-302 提案中包含以下优化:

✅ 未使用参数用下划线表示:

jdbcTemplate.queryForObject("SELECT * FROM users WHERE user_id = 1", (rs, _) -> parseUser(rs));

✅ 允许 Lambda 参数遮蔽外部变量:

String key = computeSomeKey();
map.computeIfAbsent(key, key -> key.length());

✅ Lambda 重载歧义优化:

m(Predicate<String> ps) { ... }
m(Function<String, String> fss) { ... }

目前编译器认为这两个方法冲突,未来将优化重载解析逻辑。

4.3. 模式匹配(Pattern Matching)

JEP-305 优化 instanceof 操作,自动完成类型转换:

// 旧写法
if (obj instanceof String) {
    String s = (String) obj;
    ...
}

// 新写法
if (obj instanceof String s) {
    // 直接使用 s
}

✅ 支持跨分支、跨作用域使用:

if (obj instanceof String s && s.length() > 5) {
    // s 是 String 且长度大于 5
}

4.4. 简洁方法体(Concise Method Bodies)

JEP Draft 8209434 提案支持类似 Lambda 的方法体写法:

String getName() -> name;
int length(String s) = String::length;

⚠️ 该特性仍处于草案阶段,未来可能有较大调整。

4.5. 增强枚举(Enhanced Enums)

JEP-301 曾计划为枚举引入泛型支持,但因实现复杂、与 EnumSet 冲突等原因被搁置。

5. 总结

Project Amber 为 Java 带来了诸多实用特性:

  • ✅ 已发布:局部变量类型推断、Lambda 参数类型推断、Switch 表达式
  • ⏳ 即将发布:原始字符串字面量、模式匹配等
  • 🚧 未来规划:简洁方法体、Lambda 优化、增强枚举等

这些特性虽然“小”,但极大提升了开发效率和代码可读性,是 Java 语言现代化的重要一步。建议开发者关注并逐步在项目中应用。


原始标题:Introduction to Project Amber | Baeldung