Java继承downcast ClassCastException

时间:2014-02-06 19:39:08

标签: java inheritance classcastexception downcast

给出以下代码,我有一个问题:

class A{}
class B extends A {}
class C extends B{}

public class Test {
    public static void main(String[] args) {
        A a = new A();
        A a1=new A();
        B b = new B();
//        a=b;// ok
//        b=(B)a;// ClassCastException
//        a=(A)a1;  // ok
//        a=a1;  // ok

        a=(B)a1;  // compiles ok, ClassCastException
    }
}

我的问题是以粗体显示。我的理解是,对于要编译的代码,只需要满足这些类在同一层次结构中,因此它可以工作(在树上隐式转换,在树下需要显式转换)。 每当我遇到ClassCastException时,都是因为引用指向了树上的一个对象,例如指向类型为A的对象的类型B的引用。

有问题的行似乎是指向类型A的对象的类型A的引用。(B)的转换显然是导致ClassCastException的原因。有人可以解释一下它的作用是什么吗?

注意:如果a1指向类型B的对象,那么它可以工作(只是测试它)。因此,对于编译器而言,向下转换是合法的,如果引用指向正确类型的对象,则可以使其无异常地执行。

通过将A ref a1转换为B并将其指定给a,似乎A ref a不再期望引用A类型的对象而是B?

谢谢, 肖恩。

PS我知道这有点不寻常,为Java认证做准备。通常我们向下转到左侧的类型,例如B =(B)一个; (我可以看到为什么会产生ClassCastException)。

6 个答案:

答案 0 :(得分:4)

所有B都是A,通过继承。但并非所有的A都是B的。这个特定的实例不是,因此是运行时异常。

答案 1 :(得分:2)

您正在尝试将超类引用变量强制转换为子类类型。你不能做这个。认为实际上,超类对象不能包含子类的独立方法(超类'方法除外)。

在运行时,您可以在子类中调用一个方法,该方法当然不在超类对象中。

class A{
  public void foo(){}
}
class B extends A {
  public void bar(){}
}

现在,

A a=new A();
B b=(B)a;
b.bar();

当您像这样调用编译器时,只会检查bar()中是否存在方法class B。而已。它并不关心“对象”中的内容,因为它是在运行时创建的。

但是在运行时,如前所述,对象bar()中没有a方法。 b只是指向对象 a 的引用,但a仅包含foo()而不是bar()

希望你理解。谢谢。

答案 2 :(得分:1)

垂头丧气是非法的。 A不是B,因此你不能把它变成一个。你可以把B变为A,但不能反过来。

答案 3 :(得分:1)

在您的代码示例中,变量a是对A类型对象的引用。 B级扩展了B级, 但是A类和B类之间的关系只能描述如下:

  1. B类是A类(B类的每个对象都可以合法地投射到A类)。
  2. A类不是B类(你永远不能将类型B的右值分配给A类的引用)。
  3. 这是合法的:a = (A)b;因为B类是A类。

    考虑它的一种方法是B类是A类的超集。

    如果A是包含(1,2)的集合而B是包含(1,2,3)的集合,则B是A的超集(在Java术语中:B可以转换为A)但是A不是B的超集(A不能转为B)。

    从不同的角度来看:

    • 苏格拉底是凡人。
    • 所有人都是凡人。

    苏格拉底(B级)是男人(A级)。

    这是一个无效的小主张:所有人都是苏格拉底。

答案 4 :(得分:1)

请记住合法演员表是由“IS-A”测试决定的,为什么你可以编译你的代码?,因为ClassCastException是一个未经检查的例外,因为从RuntimeException延伸

ClassCastException --- IS-A - > RuntimeException(可能合法演员的另一个例子)。

答案 5 :(得分:1)

要在Java中向下转换并避免运行时异常,请使用以下代码。

if (animal instanceof Dog) {
  Dog dogObject = (Dog) animal;
}

Animal是父类,Dog是子类。