java - 这段代码不应该产生 ClassCastException

标签 java generics classcastexception

以下代码编译运行成功,没有任何异常

import java.util.ArrayList;

class SuperSample {}

class Sample extends SuperSample {

  @SuppressWarnings("unchecked")
  public static void main(String[] args) {

    try {

      ArrayList<Sample> sList = new ArrayList<Sample>();
      Object o = sList;
      ArrayList<SuperSample> ssList = (ArrayList<SuperSample>)o;
      ssList.add(new SuperSample());

    } catch (Exception e) {
      e.printStackTrace();
    }

  }
}

不应该是 ArrayList<SuperSample> ssList = (ArrayList<SuperSample>)o; 行吗?产生一个 ClassCastException

虽然下面的代码会产生一个编译时错误错误来防止堆污染,但上面提到的代码不应该在运行时进行类似的预防吗?

ArrayList<Sample> sList = new ArrayList<Sample>();
ArrayList<SuperSample> ssList = (ArrayList<SuperSample>) sList;

编辑:

如果 Type Erasure 是这背后的原因,难道不应该有额外的机制来防止将无效对象添加到列表中吗?例如

String[] iArray = new String[5];
Object[] iObject = iArray;
iObject[0]= 5.5;  // throws ArrayStoreException

那为什么,

ssList.add(new SuperSample());

不是为了抛出任何异常吗?

最佳答案

不应该,在运行时两个列表具有相同类型的 ArrayList。这叫做 erasure .通用参数不是已编译类的一部分,它们在编译期间都会被删除。从 JVM 的角度来看,您的代码等于:

public static void main(String[] args) {
    try {
      ArrayList sList = new ArrayList();
      Object o = sList;
      ArrayList ssList = (ArrayList)o;
      ssList.add(new SuperSample());
    } catch (Exception e) {
      e.printStackTrace();
    }
}

基本上,泛型只是通过产生编译时错误和警告来简化开发,但它们根本不影响执行。

编辑:

嗯,这背后的基本概念是 Reifiable Type .我强烈推荐阅读本手册:

A reifiable type is a type whose type information is fully available at runtime. This includes primitives, non-generic types, raw types, and invocations of unbound wildcards.

Non-reifiable types are types where information has been removed at compile-time by type erasure

简而言之:数组是可修改的,而泛型集合不是。因此,当您将 smth 存储在数组中时,JVM 会检查类型,因为数组的类型在运行时存在。 Array 只是一 block 内存,而 collection 是一个普通的类,可能有任何实现。例如,它可以将数据存储在数据库中或引擎盖下的磁盘上。如果你想更深入,我建议阅读 Java Generics and Collections书。

关于java - 这段代码不应该产生 ClassCastException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20143558/

相关文章:

java - 实现 "Invite Friends"功能?

swift - 如何在使用 Swift 3 中的 Measurements 的函数调用中使用泛型

typescript - 具有通用叶包装器的可重用模型特定树结构

java - 为什么我无法从 native java Blob 转换 oracle BLOB

java - 从 ListView 获取字符串时类转换异常

java - Android RecyclerView添加和删除项目

java - Spring Hateoas 忽略查询参数

java.lang.ClassCastException : java. util.ArrayList 无法转换为 ....CrExcessMaster

java - 如何将SharedPreferences数据从settingActivity传递到MainAdapter?

typescript - 具有联合类型的泛型抛出不可分配错误