猫头鹰的深夜翻译:Java 10的JEP 286-局部变量类型推断

前言

之前面试的时候问了我是否了解JDK10的变化,一时回答不出来,所以只回答了JDK8中的函数式编程和流编程。今天看到这篇讲JAVA10的文章,顺便了解一下。

正文

JAVA10的所有新特性请参考这里。在所有的JEP中,JEP-286在社区中引发了热烈的讨论。因此今天将介绍此特性。

什么是局部变量类型推断

在JAVA8中,我们可以将下面这样使用的菱形运算符:

1
List<Map> data = new ArrayList<Map>();

转化为:

1
List<Map> data = new ArrayList<>();

RHS上的类型通过LHS上的类型来推断。

Java 10在此基础上又向前迈进了一步:

1
var data = new ArrayList<>();

局部变量类型推断允许开发人员跳过局部变量的类型声明(局部变量是指在方法定义,初始化块,for循环和其它的如if-else代码块),JDK会推断该局部变量的类型。

在哪里使用?

下面我写一个样例代码来展示使用局部变量推断var的不同的方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
public class LegalLocalVarInferenceDemo{

//在静态或是实例化的代码块中
static {
var anotherName = "Sanaulla";
System.out.println("Hello, " + anotherName);
}

public static void main(String[] args){

//局部变量
var name = "Mohamed Sanualla";
System.out.println("Hello " + name);

var data = new ArrayList<>();
data.add(Map.of("key1", "value1", "key2", "value2"));
data.add(Map.of("key11", "value11", "key22", "value22"));
data.add("hello");
System.out.println(data);

System.out.println("********** As iteration variable in enhanced for-loop ***************");
//for循环中
for ( var object : data){
System.out.println(String.format("%s of type %s", object, object.getClass().getName()));
}

System.out.println("********** As looping index in for-loop ***************");
//for循环中
for ( var i = 0 ; i < data.size(); i++ ){
var object = data.get(i);
System.out.println(String.format("%s of type %s", object, object.getClass().getName()));
}

System.out.println("********** As a return value from another method ***************");
//另一个方法的返回值
var anInteger = someAnotherMethod();
System.out.println("someAnotherMethod returned " + anInteger);

}

//As a return value in a method
public static Integer someAnotherMethod(){
System.out.println("someAnotherMethod called");
var returnObj = 12;
return returnObj;
}

}

何时不能使用?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public class IllegalLocalVarInferenceDemo{
//不准声明实例变量
//var someProperty;

//不准作为构造器的参数
// public LocalVarInferenceDemo(var param1){

// }

public static void main(String[] args){

//不准被catch块捕获
// try{
// //some operations
// }catch(var ex){

// }
}

//不准作为方法声明的参数
//public static void someMethod(var param1, var param2){
// System.out.println("Some method called");
//}

//不准作为方法的返回值
// public static var someAnotherMethod2(){
// System.out.println("someAnotherMethod called");
// var returnObj = 12;
// return returnObj;
// }
}

补充官网上的例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
Main.java:81: error: cannot infer type for local
variable x
var x;
^
(cannot use 'val' on variable without initializer)

Main.java:82: error: cannot infer type for local
variable f
var f = () -> { };
^
(lambda expression needs an explicit target-type)

Main.java:83: error: cannot infer type for local
variable g
var g = null;
^
(variable initializer is 'null')

Main.java:84: error: cannot infer type for local
variable c
var c = l();
^
(inferred type is non denotable)

Main.java:195: error: cannot infer type for local variable m
var m = this::l;
^
(method reference needs an explicit target-type)

Main.java:199: error: cannot infer type for local variable k
var k = { 1 , 2 };
^
(array initializer needs an explicit target-type)

参考资料

JRE-286