9.4.5 Java8改进的类型推断

9.4.5 Java8改进的类型推断

Java8改进了泛型方法的类型推断能力,类型推断主要有如下两方面。

  • 可通过调用方法的上下文来推断泛型的目标类型。
  • 可在方法调用链中,将推断得到的泛型传递到最后一个方法。

如下程序示范了Java8对泛型方法的类型推断。

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
class MyUtil<E> {
public static <Z> MyUtil<Z> nil() {
return null;
}

public static <Z> MyUtil<Z> cons(Z head, MyUtil<Z> tail) {
return null;
}

E head() {
return null;
}
}

public class InferenceTest {
public static void main(String[] args) {
// 可以通过方法赋值的 目标参数 来推断类型参数为String
MyUtil<String> ls = MyUtil.nil();//1

// 无需使用下面语句在调用nil()方法时指定 类型参数 的类型
MyUtil<String> mu = MyUtil.<String>nil();//2

// 可调用cons方法所需的参数类型来推断类型参数为Integer
MyUtil.cons(42, MyUtil.nil());//3
// 无需使用下面语句在调用nil()方法时指定类型参数的类型
MyUtil.cons(42, MyUtil.<Integer>nil());//4

// 希望系统能推断出调用nil()方法类型参数为String类型,
// 但实际上Java 8依然推断不出来,所以下面代码报错
// String s = MyUtil.nil().head();
String s = MyUtil.<String>nil().head();
}
}

上面程序中代码1和代码2的作用完全相同,但第代码1无须在调用 MyUtil类的nil方法时显式指定泛型参数为 String,这是因为程序需要将该方法的返回值赋值给 MyUtil<String>类型,因此系统可以自动推断出此处的泛型参数为String类型。

上面程序代码3和代码4的作用也完全相同,但代码3也无须在调用yul类的nil方法时显式指定泛型参数为 Integer,这是因为程序将nil方法的返回值作为了 MyUtil类的 cons()方法的第二个参数,而程序可以根据cons()方法的第一个参数(42)推断出此处的泛型参数为 Integer类型。

需要指出的是,虽然Java8增强了泛型推断的能力,但泛型推断不是万能的,例如如下代码就是错误的。

1
2
3
// 希望系统能推断出调用nil()方法类型参数为String类型,
// 但实际上Java 8依然推断不出来,所以下面代码报错
String s = MyUtil.nil().head();

因此,上面这行代码必须显式指定泛型的实际类型,即将代码改为如下形式

1
String s = MyUtil.<String>nil().head();