编译器判断类型方法的实际类型参数的过程称为类型推断,类型推断是相对于知觉推断的,其实现方法是一种非常复杂的过程.
根据调用泛型方法时实际传递的参数类型或返回的类型来推断,具体规则如下:
当某个类型变量只在整个参数列表中的所有参数和返回值中的一处被应用了,那么根据调用方法时该处的实际应用类型来确定,即直接调用方法时传递的参数类型或返回值来决定泛型参数的类型.例如:
swap(new String[2],2,3)-->static <E> void swap(E[] a, int i,int j)
当某个类型变量在整个参数列表中的所有参数和返回值中的多处被应用了,如果调用方法是这多处的实际应用类型都对应同一种类型来确定,这很容易凭着感觉推断出来,例如:
add(3,5)--->static <T> T add(T a,T b)
当某个类型变量在整个参数列表中的所有参数和返回值中的多处被应用了,如果调用方法是这多处的实际应用类型对应不同的类型,且没有使用返回值,这时候取多个参数中的最大交集类型,例如:下面语句实际对应的类型就是Number了,编译没问题,只是运行时出问题:
fill(new Integer[3],5.5f)--->static <T> void fill(T[] a,T b)
当某个类型变量在整个参数列表中的所有参数和返回值中的多处被应用了,如果调用方法是这多处的实际应用类型对应不同的类型,且有使用返回值,这时候优先考虑返回值的类型,例如:下面语句实际对应的类型就是Integer,变异将报告错误,将变量x的类型改为float,对比eclipse报告的错误提示,接着再将变量x类型改为Number,则没有错误:
int x=add(3,3.5f)-->static <T> T add(T a,T b)
参数类型的类型推断具有传递性,下面第一种情况推断实际参数类型为Object,编译没问题,而第二种情况则根据参数化的Vector类实例将类型变量直接确定为String类型,编译将出现问题:
copy(new Integer[5],new String[5])-->static <T> void copy(T[] a,T[] b)
copy(new Vector<String>(),new integer[5])-->static <T> void copy(Collection<T> a,T[] b)