“必须编写供人们经常阅读的、却·偶然地供机器执行的程序。”-Harold Abelson
在Java 10中,添加了新功能Local-Variable Type Inference。目的是在使用初始化程序声明局部变量时减少样板代码并提高可读性。
让我们通过一个例子来理解这一点。在不使用Local-Variable Type Inference的情况下编写了以下代码:
List employees = Arrays.asList(new Employee(1, "Ashish", 28, 10000)
, new Employee(2,"Ajay", 29, 1000)
, new Employee(3,"Abhishek", 29, 10000));
Map map = employees
.stream()
.collect(Collectors.toMap(Employee::getId,Employee::getName));
Map> listMap = employees
.stream()
.collect(Collectors.groupingBy(Employee::getSalary));
重构后,使用Java 10局部变量类型推断:
var employees = Arrays.asList(new Employee(1, "Ashish", 28, 10000)
, new Employee(2,"Ajay", 29, 1000)
, new Employee(3,"Abhishek", 29, 10000));
var employeeMap = employees.stream()
.collect(Collectors.toMap(Employee::getId,Employee::getName));
var groupedMap = employees.stream()
.collect(Collectors.groupingBy(Employee::getSalary));
在上面的重构代码中,编译器可以通过查看RHS声明来自己推断声明的类型。这些只是一些示例,可以帮助您理解该功能以及我们如何使用局部变量类型推断。
现在,让我们了解可以在哪里使用局部变量类型推断以及在哪里不能使用局部变量类型推断。
可以使用的地方
局部变量初始化器
增强的forloop中的索引
在传统的forloop中声明的本地人
try-with-resources语句的资源变量
隐式类型的lambda表达式的形式参数。(在Java 11中添加了支持)
以下代码段显示了一些有效的示例:
var str = new String("Hello");
var list = new ArrayList();
var integerList = List.of(1,2,3,4);
for (var data :integerList) {
System.out.println(data);
}
for (var i = 1; i <= integerList.size(); i++) {
System.out.println(i);
}
var path = Paths.get("/src/main/resources/app.log");
try(var file = Files.lines(path)){//some code}
无法使用的地方
字段
方法参数
方法返回类型
局部变量声明,无需任何初始化
不能使用null进行初始化
在下面的代码片段中说明如果以不支持的方式使用它将出现什么编译器错误。
//无法在没有初始化程序的情况下推断类型:'var'var x;//无法推断类型:lambda表达式需要显式的目标类型var f = () -> {};//无法推断类型:变量初始值设定项为“ null”var g = null;//此处不允许使用数组初始化程序var k = {1, 2};
好处
由于此功能与可读性相关,因此有些人会喜欢它,而有些人会讨厌它。如果在代码检查过程中有人说他/她不知道var的声明类型,则意味着对他人来说不是很清楚,因此也许切换回“老式”方式来显式声明类型是毕竟还不错。同样,在某些情况下,声明的类型非常明显,因此您可以跳过显式声明的类型,而改用var。