泛型——泛型方法

时间:2021-02-08 17:35:05

示例一:

最初学习泛型方法时,想到一个可以使用泛型方法的例子,这个例子可以在一定程度上说明泛型方法的定义和使用,但是后来发现这个例子如果用泛型方法来实现的话非常不恰当。

先将就着看一下这个例子,后面再说明一下为什么会不恰当。

有一个需求,定义一个方法,去掉一个已有数组(非int、byte等基本数据类型的数组)中的重复元素,该方法返回一个对应数据类型的新数组。

因为数组元素的数据类型太多了,可以考虑使用Object类型的数组;但是方法必须返回与原始数组中元素类型相同的新数组,这就要求必须能在方法中知道原始数组元素的数据类型,显然如果使用Object数组的话是无法知道具体的元素数据类型的,所以考虑使用泛型方法来实现。代码如下:

public static <T> T[] removeRepetitionGeneric(T[] srcArray){
ArrayList<T> tempList = new ArrayList<>();
for(T t : srcArray){
if(!tempList.contains(t))
tempList.add(t);
}
return (T[])tempList.toArray();
}

这个方法在编译时没有错误,但是有一个警告:

warning: [unchecked] unchecked cast
return (T[])tempList.toArray();
^
required: T[]
found: Object[]

这个警告有可能导致程序出现异常,也有可能不出现异常,这取决于你如何使用该方法的返回值。先看一个正常的调用:

public static void main(String[] args){
Integer[] intArray = new Integer[]{4, 2, 4, 6, 1, 2, 4, 7, 8};
String[] strArray = { "java", "c++", "ruby", "c#", "java", "c++" };

System.out.println(Arrays.toString(removeRepetitionGeneric(intArray)));
System.out.println(Arrays.toString(removeRepetitionGeneric(strArray)));
}

上面的对该方法的调用不会出现异常;但下面的调用方式会出现运行时异常:

public static void main(String[] args){
Integer[] intArray = new Integer[]{4, 2, 4, 6, 1, 2, 4, 7, 8};
intArray = removeRepetitionGeneric(intArray);
System.out.println(Arrays.toString(intArray));
}

异常信息如下:

Exception in thread "main" java.lang.ClassCastException: 
[Ljava.lang.Object; cannot be cast to [Ljava.lang.Integer;

对比2次调用,区别在于,第一次调用时,我们把方法的返回值直接传给了Arrays的toString方法,Arrays的toString方法有一个重载的toString(Object[] a)的形式,所以该方法的返回值无论是Object[]类型,还是Integer[]类型,都可以传给Arrays的toString方法;但是第二次调用时,我们把返回值赋给了一个Integer[]类型的变量,也就是这次赋值导致了异常。

虽然我们在该方法返回时,将Object[]强制类型转换成Integer[]类型,但是该方法返回的依然是Object[]类型的结果,这就是为什么第一次调用正常,而第二次调用异常的原因。