java 中以奇怪的方式出现 ClassCastException 和编译问题

ClassCastException and compilation issue in strange manner in java

下面的代码片段有一个奇怪的地方behaviour.can谁能详细解释一下

下面的代码抛出 ClassCastException 但 inks.get(0) 给出了无法转换为 BlackInk 的 ColorInk,因为没有 IS-A 关系。 然后应该给出编译器错误,为什么它编译成功并抛出 ClassCastException。

    import java.util.ArrayList;
    public class ListAccess {
      public static void main(String[] a){
        ArrayList<Ink> inks=new ArrayList<Ink>();
     inks.add(new ColorInk());
     inks.add(new BlackInk());
     Ink ink=(BlackInk) inks.get(0);
  }
}

class Ink{}
class ColorInk extends Ink{}
class BlackInk extends Ink{}

下面的代码又很奇怪,当只有 Arraylist 泛型是 ColorInk 时,它编译失败而不是 ClassCastException没有 IS-A 关系的 BlackInk。

import java.util.ArrayList;
        public class ListAccess {
          public static void main(String[] a){
            ArrayList<ColorInk> inks=new ArrayList<Ink>();
         inks.add(new ColorInk());
         Ink ink=(BlackInk) inks.get(0);
      }
    }

class Ink{}
class ColorInk extends Ink{}
class BlackInk extends Ink{}

您注意到的行为与继承的基本规则有关。

对于第一个片段,您将 Ink 向下转换为 BlackInk :

Ink ink=(BlackInk) inks.get(0);

编译器接受它作为 Ink 可能是 BlackInk。但是如果转换在运行时无效,向下转换可能仍然会失败。这就是 inks.get(0) 引用 ColorInk 时发生的情况。

在第二个片段中:

ArrayList<ColorInk> inks=new ArrayList<Ink>();
...
Ink ink=(BlackInk) inks.get(0);

编译器阻止你,因为你想将一个声明类型的对象转换为一个它不兼容的类型:根据你定义的层次结构,ColorInk 不能是 BlackInk。编译器不会等待它在运行时失败,因为它可能使编译立即失败,这样更好。