Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/359.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 用类型擦除欺骗集合_Java_Casting_Type Erasure - Fatal编程技术网

Java 用类型擦除欺骗集合

Java 用类型擦除欺骗集合,java,casting,type-erasure,Java,Casting,Type Erasure,我试图举例说明类型擦除来向某人解释它,但我发现了一些意想不到的事情。以下是我尝试过的片段: Object o = new ArrayList<Integer>(); List<String> list = (List<String>) o; list.add("Oups"); System.out.println(list); 哪个会引发异常(ArrayStoreException)?(由于问题的更改而更新。) 最后一行不会抛出异常,因为ArrayList的

我试图举例说明类型擦除来向某人解释它,但我发现了一些意想不到的事情。以下是我尝试过的片段:

Object o = new ArrayList<Integer>();
List<String> list = (List<String>) o;
list.add("Oups");
System.out.println(list);
哪个会引发异常(
ArrayStoreException
)?

(由于问题的更改而更新。)

最后一行不会抛出异常,因为
ArrayList
toString()
实现根本不关心元素类型。它简单地对存储在其内部
对象[]
元素数组中的每个对象递归调用
toString()
,因此不需要检查其元素的运行时类型

但是,该代码实际上也不会失败:

List<Integer> il = new ArrayList<Integer>();
Object o = il;
List<String> sl = (List<String>)o;
sl.add("Oups");
System.out.println(il.get(0));
因为现在您正在执行一个操作,该操作假定元素是一个
整数
,并且转换包含在生成的代码中

另一方面,基元数组具有其元素类型的运行时知识,并将在每次插入时断言它。

(由于问题的更改而更新。)

最后一行不会抛出异常,因为
ArrayList
toString()
实现根本不关心元素类型。它简单地对存储在其内部
对象[]
元素数组中的每个对象递归调用
toString()
,因此不需要检查其元素的运行时类型

但是,该代码实际上也不会失败:

List<Integer> il = new ArrayList<Integer>();
Object o = il;
List<String> sl = (List<String>)o;
sl.add("Oups");
System.out.println(il.get(0));
因为现在您正在执行一个操作,该操作假定元素是一个
整数
,并且转换包含在生成的代码中


另一方面,基元数组在运行时知道其元素类型,并且在每次插入时都会断言它。

由于运行时的类型擦除,它的类型是
对象,并且您的
列表是空的,您从不迭代它

List<Integer> o = new ArrayList<Integer>();
List<String> list = (List<String>) (Object) o;
list.add("Oups");
for (Integer i : o) { // <-- Iterate the List<Integer>
    System.out.println(i);
}

由于运行时的类型擦除,它的类型是
Object
,并且您的
列表是空的,并且您从不迭代它

List<Integer> o = new ArrayList<Integer>();
List<String> list = (List<String>) (Object) o;
list.add("Oups");
for (Integer i : o) { // <-- Iterate the List<Integer>
    System.out.println(i);
}

ArrayList
中的数组是一个
对象[]
,而不是一个
整数
,因此为其分配任何任意对象都没有问题。当您尝试执行
list.get(0)
时,它将中断,因为编译器将插入一个隐式转换,
(Integer)list.get(0)
,该转换将失败


(这是堆污染是一个严重缺陷的原因之一;故障可能发生在远离实际存在缺陷的代码的地方。)

数组列表中的数组是一个
对象[]
,而不是
整数
,因此为其分配任何任意对象都没有问题。当您尝试执行
list.get(0)
时,它将中断,因为编译器将插入一个隐式转换,
(Integer)list.get(0)
,该转换将失败


(这就是堆污染是一个令人讨厌的bug的原因之一;失败可能发生在远离实际bug的代码的地方。)

我当时应该包括真正的最后一行,这是列表的打印。我会更新我的帖子。为什么打印列表不会导致抛出异常?添加“真正的最后一行”显然使问题大不相同,因此我完全修改了答案:谢谢你的回答;)我当时应该包括真正的最后一行,那是列表的打印件。我会更新我的帖子。为什么打印列表不会导致抛出异常?添加“真正的最后一行”显然使问题大不相同,因此我完全修改了答案:谢谢你的回答;)我还尝试了一个填充的
列表
,忘了提及我的阅读。哈哈,我已经阅读了文档的这一部分,因为上面有很多问题,但我似乎已经记住,在这种情况下,强制转换不会引发异常,而插入会引发异常。我现在明白了数组和泛型之间的混淆,因为
Integer[]
String[]
实际上是两个不同的类,而
List
List
至少在Java@Dici对于数组的情况,我可以参考并指出数组扩展了
Object
(它们是实例)。我还尝试了填充的
列表
,忘了提及itRead about。哈哈,我已经阅读了文档的这一部分,因为上面有很多问题,但我似乎已经记住,在这种情况下,强制转换不会引发异常,而插入会引发异常。我现在知道这是数组之间的混淆nd泛型,因为
Integer[]
String[]
实际上是两个不同的类,而
List
List
至少在Java@Dici对于数组的情况,我可以参考并指出数组扩展了
Object
(它们是实例)。
Exception in thread "main" java.lang.ClassCastException: 
    java.lang.String cannot be cast to java.lang.Integer