1. 什么是 Project Amber
Project Amber 是由 Java 和 OpenJDK 开发团队发起的一个长期项目,目标是为 JDK 带来一些小而精的改进,让 Java 开发体验更加舒适。该项目自 2017 年启动以来,已经在 Java 10、11 中交付了部分特性,其余功能也陆续在 Java 12 及后续版本中落地。
这些改进都是以 JEP(JDK Enhancement Proposal) 的形式提出的。
2. 已交付的更新
截至目前,Project Amber 已成功将一些特性集成进 JDK 的正式版本中,包括 JEP-286 和 JEP-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;
- 显式赋值为
null
:var nullType = null;
- Lambda 表达式(无类型信息):
var lambdaType = () -> {};
⚠️ 特殊情况:如果 null
是某个方法的返回值,是可以推断出类型的:
Optional<String> name = Optional.empty();
var nullName = name.orElse(null); // 推断为 String
💡 var
是一个特殊类型名,不是关键字,因此可以作为变量名使用,但强烈建议不要这么做,容易引起歧义。
✅ 局部变量也可以加上修饰符,如 final
、synchronized
等:
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 语言现代化的重要一步。建议开发者关注并逐步在项目中应用。