java不能创建参数化类型的泛型数组

在java泛型中是不能实例化参数化类型的数组的,例如:

Pair<String>[] table = new Pair<String>[10]; //Error

这是为什么呢?其实主要是为了避免数组里出现类型不一致的元素。

我们先看一下,数组是否可以存储其它类型元素

Pair[] table = new Pair[10];
table[0] = new Object(); //编译错误

很明显直接存储,编译器会报错。那么将数组向上转换一下,再存储呢?

Pair[] table = new Pair[10];
Object[] o = table; //自动转换
o[0] = new Object();

此时编译器是不会报错的,但是运行时会抛出ArrayStoreException异常

说明了数组存储检查是很严格的,它只能存储创建时元素类型

但是,泛型擦除会破坏这种机制,举例:

Pair<String>[] table = new Pair<String>[10] //假设可以
Object[] o = table; //泛型擦除变为Pair[],向上自动转换为Object[]
o[0] = new Pair<Double>();

你会发现,此时Pair数组里存储了Pair元素

当然以下情况还是不行的:

o[1] = new Object(); // 编译不报错,运行抛出异常

总之java不允许创建参数化的泛型数组,是为了保护数组安全性。

另外,虽然参数化的泛型数组不能创建,但是可以创建通配符的泛型数组。

Pair<?>[] table = new Pair<?>[10];

这是可以的,因为new Pair表示数组可以存储任意参数的Pair,如Pair和Pair等等。

另外,还可以这么创建

Pair<String>[] table = new Pair[10]; //兼容转换,并不是父子关系
table[0] = new Pair<Double>; //编译错误

此时,数组的实际类型是虽然是Pair,但是声明为Pair,所以报错。
原因在于,泛型类型和原始类型可以转换,但却不是继承关系。按理来说,Pair可以转为Pair,应该可以存储,但此时声明的Pair却不是Pair的父类,所以Pair不能存储。

但是,以下方式可以正常运行

Object[] o =table;
o[0] = new Pair<Double>;

你可能感兴趣的:(Java)