Java 中为什么禁止泛型数组

Steven迪文 2022-06-23 17:45:11 阅读数:153

javaCSDN数组禁止technology-development

首先理解两个概念。

1. 共变数组(covariant array)

在 Java 中, array具有共变性。

共变性的意思是说,一个 类型为 T[ ] 的数组可以包含,类型为 T 的元素或者 subtype 类型为 T 的元素。

所以我们可以这样做:

Number[] numbers = newNumber[3];
numbers[0] = newInteger(10);
numbers[1] = newDouble(3.14);
numbers[2] = newByte(0);

不仅如此,如果 S 是 T 的 subtype, 一个类型为 S[ ] 的数组也是类型 T [ ]数组的 subtype。例如 Integer 是 Number 的 Subtype, 我们可以这么做:

Integer[] myInts = {
1,2,3,4};
Number[] myNumber = myInts;

如果这样做呢? 不通过类型对象直接赋值。

myNumber[0] = 3.14;

上面的代码直接给 类型为T[ ] 的数组赋值, 在编译期间是没有问题的,

但如果运行这段代码,将引发一个错误警告 ArrayStoreException

这是因为在运行期间,Java 知道这个数组被实例化为整形数组。

2. 类型擦除(type erasure)

在 Java 泛型中,泛型类型是一种类型信息,且在编译之后被编译器丢弃。

所以泛型的类型信息,在运行期间是不存在的。

这个过程叫做「类型擦除」。

//例如:
//Java 是一个面对对象语言, 所有的元素在 Java 中都关联着类和对象。
//Java 的 Object 类是所有类的父类。
//所以 
𝚂𝚝𝚛𝚒𝚗𝚐[ ] 是 𝙾𝚋𝚓𝚎𝚌𝚝[] 的subtype
但 𝚂𝚝𝚊𝚌𝚔<𝚂𝚝𝚛𝚒𝚗𝚐> 不是 𝚂𝚝𝚊𝚌𝚔<𝙾𝚋𝚓𝚎𝚌𝚝> 的 subtype

另外,泛型没有共变性。

3. 为什么禁止泛型数组?

继续上一个例子:

//因为类型擦除,泛型类型在运行期间,Stack 的 String 类型会被擦除成 Stack。
//所有的 Stack 泛型类型分享同一个 Stack.class
//但数组中,不同类型的数组都有自己的 class。
//结合数组的共变性,即便像 1.中的 不通过类型对象直接赋值。
//我们能在编译期间能暂时骗过编译器,但在运行期间,Java 知道我们在做什么,
//也就是数组的类型在运行期间不能被擦除,这与泛型的类型擦除相矛盾,所以 Java中禁止了泛型数组。
版权声明:本文为[Steven迪文]所创,转载请带上原文链接,感谢。 https://blog.csdn.net/weixin_46442179/article/details/125394706