Java 10 局部变量类型推断:var 关键字深度解析
JEP 286:局部变量类型推断
Java 10 引入 var 关键字,允许在声明局部变量时省略显式类型,由编译器根据初始化表达式推断类型。这是 Java 向类型推断迈出的重要一步,显著减少样板代码。
语法对比
// 旧写法
String name = "Welcome to tutorialspoint.com";
List<String> list = new ArrayList<>();
Map<Integer, String> map = new HashMap<>();
// 新写法(Java 10+)
var name = "Welcome to tutorialspoint.com"; // 推断为 String
var list = new ArrayList<String>(); // 推断为 ArrayList<String>
var map = new HashMap<Integer, String>(); // 推断为 HashMap<Integer, String>
核心限制与规则
- 仅限局部变量:成员变量、方法参数、返回类型、字段初始化均不支持。
- 必须初始化:声明时必须赋值,否则编译器无法推断类型(
var x;编译报错)。 - 不能推断为 null:
var x = null;非法,因无法确定类型。 - 支持循环初始化块:
for (var i = 0; i < 10; i++)、for (var s : list)均合法。 - 无运行时开销:编译期推断,字节码与显式类型完全一致,性能零损耗。
- 类型不可变:推断后类型固定,不能后续赋值不同类型对象。
- 不改变 Java 静态类型本质:仍是强静态类型语言,
var仅为语法糖。
典型应用场景
1. 简化复杂泛型声明
// 旧
Map<String, List<Map<Integer, String>>> complexMap = new HashMap<>();
// 新
var complexMap = new HashMap<String, List<Map<Integer, String>>>();
2. 流式 API 链式调用中间变量
var filtered = list.stream()
.filter(s -> s.length() > 3)
.map(String::toUpperCase)
.collect(Collectors.toList()); // 类型自动推断为 List<String>
3. try-with-resources 资源变量
try (var input = new FileInputStream("data.txt");
var reader = new BufferedReader(new InputStreamReader(input))) {
// ...
}
完整示例
import java.util.List;
public class Tester {
public static void main(String[] args) {
var names = List.of("Julie", "Robert", "Chris", "Joseph");
// 增强 for 循环
for (var name : names) {
System.out.println(name);
}
System.out.println();
// 传统 for 循环
for (var i = 0; i < names.size(); i++) {
System.out.println(names.get(i));
}
}
}
输出:
Julie
Robert
Chris
Joseph
Julie
Robert
Chris
Joseph
最佳实践建议
- 类型从右侧表达式显而易见时使用
var(如构造器调用、工厂方法)。 - 类型不明显或为基本类型/简单对象时,保留显式类型以提高可读性。
- 避免在大作用域或复杂逻辑中滥用
var,以免降低代码自文档性。 - 配合
final使用(final var)表达不可变意图。
java