泛型是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 <>());