Java8新特性之类型推断

泛型是Java SE 1.5的新特性,泛型的本质是参数化类型。 一般泛型的定义:

1
2
3
List<People> box = new ArrayList<People>();
box.add(new People());
People people =box.get(0);

泛型的优点很明显第一提高了类型的安全,第二消除强制类型的转换,但是尴尬的地方就是每次定义时都要写明泛型的类型,这样显示指定感觉有些冗长。 Java7的泛型类型推断改进:

1
Map<String, String> map = new HashMap<>(); //注意后面的"<>"

上述Map的定义编译器会根据变量声明时的泛型类型自动推断出实例化HashMap时的泛型类型。注意new HashMap后面的“<>”,只有加上这个“<>”才表示是自动类型推断,否则就是非泛型类型的HashMap,并且在使用编译器编译源代码时会给出一个警告提示。
Java SE 7在创建泛型实例时的类型推断是有限制的:
只有构造器的参数化类型在上下文中被显著的声明了,才可以使用类型推断,否则不行。

1
2
3
4
List<String> list = new ArrayList<>();
list.add("A");
//下面addAll方法无法通过编译,由于addAll期望获得Collection<? extends String>类型的参数
list.addAll(new ArrayList<>());

Java8泛型类型推断改进:

1.支持通过方法上下文推断泛型目标类型。

2.支持在方法调用链路当中,泛型类型推断传递到最后一个方法。 官方例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class List<E> {

   static <Z> List<Z> nil() { ... };
   static <Z> List<Z> cons(Z head, List<Z> tail) { ... };
   E head() { ... }
}



//通过方法赋值的目标参数来自动推断泛型的类型
List<String> l = List.nil();
//而不是显示的指定类型
//List<String> l = List.<String>nil();
//通过前面方法参数类型推断泛型的类型
List.cons(42, List.nil());
//而不是显示的指定类型
//List.cons(42, List.<Integer>nil());

所以上面addAll出错的例子在Java8中依据方法参数类型推断就不会出错了。

1
2
3
4
5
//下面代码Java8通过编译
List<String> list = new ArrayList<>();
list.add("A");
//根据add方法中的"A"参数推断new ArrayList<>()的类型为new ArrayList<String>()
list.addAll(new ArrayList<>());