通常来说,泛型总是和数组无缘,比如下面这种用法:
Peel<Banana>[] peels = new Peel<Banana>[10];
上面的代码将无法通过编译,因为我们没法创建一个泛型数组。其原因为:由于类型擦除的原因,泛型参数所拥有的类型信息并不确定,但是数组总是要求持有确切的类型,以保证类型安全,但是我们可以参数化数组本身的类型:
import java.util.*;
import static net.mindview.util.Print.*;
class ClassParameter<T>
//使用泛型类将参数化数组
{
public T[] f(T[] arg){
return arg;
}
}
class MethodParameter
{
public static <T> T[] f(T[] arg){
//使用泛型方法参数化数组
return arg;
}
}
public class ParameterizedArrayType
{
public static void main(String[] args){
Integer[] ints = {1,2,3,4,5};
Double[] doubles = {1.1, 2.2, 3.3, 4.4, 5.5};
Integer[] ints2 = new ClassParameter<Integer>().f(ints);
print(Arrays.toString(ints2));
//输出:[1, 2, 3, 4, 5]
Double[] doubles2 = new ClassParameter<Double>().f(doubles);
print(Arrays.toString(doubles2));
//输出:[1.1, 2.2, 3.3, 4.4, 5.5]
ints2 = MethodParameter.f(ints);
print(Arrays.toString(ints2));
//输出:[1, 2, 3, 4, 5]
doubles2 = MethodParameter.f(doubles);
print(Arrays.toString(doubles2));
//输出:[1.1, 2.2, 3.3, 4.4, 5.5]
}
}
ClassParamter通过泛型类参数化数组,MethodParameter.f()通过泛型静态方法参数化数组,两种方法都是可行的 ,只不过可以看出来,使用参数化类每次都要创建一个实例,明显参数化方法要简单的多,这个时候我就有一个问题了,既然存在类型擦除,那么参数化数组中能不能放入其他类型的数据呢:
doubles2[1] = 1L;//无法将Long转换为double类型
所以显然是不行的。
虽然我们没办法直接创建一个泛型数组,但是我们可以创建一个非泛型的数组然后将它转型:
import java.util.*;
//import static net.mindview.util.Print.*;
class BerylliumSphere{}
public class ArrayOfGenerics
{
@SuppressWarnings("unchecked")
public static void main(String[] args){
List<String>[] ls;
List[] la = new List[10];
ls = (List<String>[])la;
ls[0] = new ArrayList<String>();
//ls[1] = new ArrayList<Integer>();
//因为泛型的原因上面的代码将无法通过编译
Object[] objects = ls;
objects[1] = new ArrayList<Integer>();
//由于Obejct是所有类的基类,所以上面的代码将可以通过编译
List<BerylliumSphere>[] spheres = (List<BerylliumSphere>[])new List[10];
for(int i=0; i<spheres.length; i++)
spheres[i] = new ArrayList<BerylliumSphere>();
}
}
上面这种方法都是建立在一个操作上的:
List<String>[] ls;
这个操作将不会引起警告,并且我们将创建具有斜边类型的数组。这一切都将归功于容器。
但是我们将不能直接创建泛型数组:
import java.util.*;
//import static net.mindview.util.Print.*;
public class ArrayOfGenericType<T>
{
T[] array;//这样是可以的,因为T[]被擦除为Object[]
@SuppressWarnings("unchecked")
public ArrayOfGenericType(int size){
//array = new T[size];
//上面的代码将警告编译错误,因为泛型并不是确切类型
array = (T[]) new Object[size];
//但是我们可以创建一个Object数组,然后将他转型
}
//public <U> U[] makeArray(){
//return new U[10];
//上面的代码将警告编译错误,因为U并不是一个确切类型
//}
}
通过参数化类,可以另辟蹊径的实现参数化数组。