为什么List <SuperClass>对象可以强制转换为子类对象? - java

我发现,情况1和情况3可以没有错误地进行编译,但情况2可以被编译。(SubClassB扩展了SuperClassA,它是抽象类)
我想知道的是,为什么情况1和情况3没有编译错误。
如果是JDK错误,为什么情况2无法通过强制转换检查?

// case 1        
List<SuperClassA> a = new ArrayList<>();
SubClassB b = (SubClassB) a; 

// case 2
List<Number> m = new ArrayList<>();
Long n = (Long) m; //Error:(xx,yy) java: incompatible types: java.util.List<java.lang.Number> cannot be converted to java.lang.Long

// case 3
List<Exception> e = new ArrayList<>();
RuntimeException d = (RuntimeException) e;

参考方案

请注意,情况1和情况3都将在运行时失败。

在编译时,仅在语言规范如此说明时,编译器才会抱怨不兼容的强制类型转换。语言规范允许情况1和3,因为它们不会100%失败。

就编译器而言,案例1不会100%失败,因为案例1认为a可以包含实现List<SuperClassA>的任何类型的实例。如果有一个SubclassB的子类实际上实现了List<SuperClassA>怎么办?如果a实际上包含SubclassB子类的实例怎么办?然后,转换将成功!

情况2也是一样。如果存在实际上实现RuntimeExceptionList<Exception>子类,该怎么办?如果e实际上包含RuntimeException子类的实例怎么办?然后,转换将成功!

情况2显示错误,因为Longfinal。不可能有实现List<Number>的子类,所以它肯定会失败。

这在规范的§5.5.1中指定(斜体为相关位):

给定编译时参考类型S(源)和编译时参考类型T(目标),如果由于以下规则而没有发生编译时错误,则存在从S到T的转换转换。

...

如果S是接口类型:

  • 如果T为数组类型,则S必须为java.io.SerializableCloneable类型(唯一实现的接口
    数组),否则会发生编译时错误。
  • 如果T是不是final(第8.1.1节)的类或接口类型,则如果存在T的超类型X和S的超类型Y,则
    X和Y都是可证明不同的参数化类型,并且
    X和Y的擦除相同,则发生编译时错误。
  • 否则,强制转换在编译时始终是合法的(因为即使T
    不实现S,则可能是T的子类)。

  • 如果T是最终的类类型,则:

    –如果S不是参数化类型或原始类型,则T必须实现S,否则会发生编译时错误。

  • Java中的<<或>>>是什么意思? - java

    This question already has answers here: Closed 7 years ago. Possible Duplicate: What does >> and >>> mean in Java?我在一些Java代码中遇到了一些陌生的符号,尽管代码可以正确编译和运行,但对于括号在此代码中的作用却感…

    菱形运算符<>是否等于<?> - java

    我在util.TreeSet类中发现,其中一个构造函数正在使用具有空泛型类型的新TreeMap调用另一个构造函数。 public TreeSet(Comparator<? super E> comparator) { this(new TreeMap<>(comparator)); } new TreeMap<>是什么意思…

    休眠映射<键,设置<值>> - java

    我有以下表格:@Entity @Table(name = "events") Event --id --name @Entity @Table(name = "state") State --id --name @Entity @Table(name = "action") Action --id …

    无法从ArrayList <String>转换为List <Comparable> - java

    当我写下面的代码时,编译器说 无法从ArrayList<String>转换为List<Comparable>private List<Comparable> get(){ return new ArrayList<String>(); } 但是当我用通配符编写返回类型时,代码会编译。private List&l…

    合并List <T>和List <Optional <T >> - java

    鉴于: List<Integer> integers = new ArrayList<>(Arrays.asList( 10, 12 )); List<Optional<Integer>> optionalIntegers = Arrays.asList( Optional.of(5), Optional.em…