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

时间:2018-09-08 07:43:24

标签: java classcastexception

以下代码段的行为很奇怪。任何人都可以详细解释

下面的代码引发ClassCastException,但是inks.get(0)给出了ColorInk,由于没有IS-A关系,它无法转换为BlackInk。 然后应该给出编译器错误,为什么编译成功并引发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,这使得两种情况下的list.get(0)返回ColorInk并将其转换为没有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{}

1 个答案:

答案 0 :(得分:1)

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

对于第一个片段,您将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。编译器不会等待它在运行时失败,因为它可能使编译立即失败,这更好。