java泛型的Type Inference

关于type inference

常见场景:
1、泛型
类实例化,调用构造器时:

1
Map<String, List<String>> myMap = new HashMap<>();

Java 7 diamond语法:调用泛型类的构造器时可以用空尖括号只要上下文可推断。称作diamond。
注意:想让type inference推断时必须要有尖括号,不写尖括号会导致unchecked。
2、调用普通泛型方法时:
例1:

1
BoxDemo.<Integer>addBox(Integer.valueOf(10), listOfIntegerBoxes);

可简写为:

1
BoxDemo.addBox(Integer.valueOf(10), listOfIntegerBoxes);

例2:

1
2
3
List<String> list = new ArrayList<>();
list.addAll(new ArrayList<? extends String>);//在java7中要具体写出
//list.addAll(new ArrayList<>());//也可以,java8允许

这里List的addAll方法的参数expect的是ArrayList<? extends String>(),根据第4种场景的说明,编译器推测newArrayList()是个newArrayList<? extends String>(),因此list.addAll(new ArrayList<>()) 也是允许的。
这里要记住的要点就是 要传给方法它expect的参数类型的实例。不管这个实例是个对象应用还是个基本类型的值。

3、调用有返回值的泛型方法并赋值时,根据target types推断参数类型:

1
2
static <T> List<T> emptyList();
List<String> listOne = Collections.emptyList();

4、java 8:根据target types推断参数类型扩展至可以根据target argument来推断
例子:

1
2
3
4
void processStringList(List<String> stringList) {
// process stringList
}
processStringList(Collections.emptyList());

这里Collections.emptyList()返回的时List,而processStringList方法expect的参数时List,于是编译器推测T是String

5、泛型/非泛型类都可以有泛型的构造器。
泛型方法中的泛型构造器:

1
2
3
4
5
class MyClass<X> {
<T> MyClass(T t) {
// ...
}
}

对它的调用:
1)

1
new MyClass<Integer>(“”)

//这句说明创建了一个X为Integer的MyClass实例,并调用的是这个构造器,且构造器的类型参数T是String,这是java通过参数””type inference出来的。
2)

1
MyClass<Integer> myObject = new MyClass<>("");

//这里的<>和“”都利用了type inference