为什么以下代码给出了一个classcast异常?

时间:2015-05-27 13:15:44

标签: java inheritance

给出以下代码:

//Super class 
class A {
    void m1() {
        System.out.println("A");
    }
}

//Extending the super class  
class B extends A {
    void m1() {
        System.out.println("B");
    }
}

// Class with the main method
public class C extends B {
    void m1() {
        System.out.println("C");
    }
}

//in some main method
B b1 = new B(); //creating B object
System.out.println(b1 instanceof A); //gives true
B b = (B) new A();
b.m1();
  1. instanceof运算符为true,因此B是类A的对象。
  2. 但是,为什么在A B ClassCastException时,B提出AnumOfDocuments0的子类型?

8 个答案:

答案 0 :(得分:7)

new A();根本不是B

就像你说“每只动物都是猫,没有例外”一样。这不是真的。

但是,将B投射到A是正确的(因为每只猫都是动物,没有例外):

A a = (A) new B();

答案 1 :(得分:1)

A a = new B(); // is fine as B inherits A
B b = new A(); // is NOT fine as A does not inherit any thing from B

答案 2 :(得分:0)

B是A的一个实例,它是正确的。但是A不是B的实例。这就是你得到例外的原因。

答案 3 :(得分:0)

B b = (B) new A();是错误的陈述,因为A不会继承B;而B继承A

答案 4 :(得分:0)

由于一些原因,允许这样的铸造是不安全的。

1)假设您添加了B其他A无法使用的字段

class A {
    void m1() {
        System.out.println("A");
    }
}

class B extends A {
    void m1() {
        System.out.println("B");
    }

    private int x;
    public void setX(int x) {
        this.x = x;
    }
}

现在让我们假设这个转换会起作用

B b = (B) new A();

因此b将保留A的实例。但稍后我们可以尝试从setX引用

中调用B
b.setX(1);

应该没问题,因为没有强制转换异常,因此来自B引用的对象应该能够支持此调用。
您怎么看?JVM应该如何应对下一行?这样的代码应该被允许吗?

不,基地A不知道应该为setX执行哪些代码,即使它知道它,它也没有int x字段存储其数据。因此,为了防止这种情况,JVM会抛出ClassCastException。

2)您可以这样说:&#34; 好的,但我的B没有更改界面,它不会向A <添加任何新内容/ EM>&#34 ;.你是对的,但在这种情况下允许转换也很危险,因为从B调用方法时,你应该能够期望它们的行为方式与B类或其子类中描述的方式相同。

让我们说我们正在建立赛车游戏,我们有课程

class Car{
    int getMaxSpeed(){
        200;
    }
}
class LimitedSpeedCar extends Car{
    int getMaxSpeed(){
        return 30;
    }
}

现在,您只想为速度有限的汽车创建赛道。因此,您正在创建LimitedSpeedCar[]数组,以仅存储速度有限的汽车。但是猜猜是什么,因为

B b = (B) new A();

工作正常意味着

LimitedSpeedCar lsc = (LimitedSpeedCar) new Car();

也会有效,所以我们可以加入我们的赛车,没有限制,这不是我们想要的。

答案 5 :(得分:0)

BA的子类,您无法将A投射到B。实际上,新A对象的具体类可能是B之外的另一个类(比如扩展C的类A)。因此,您无法确认AB的实例。

答案 6 :(得分:0)

类型B的对象可以转换为A类变量,但不能转换为其他方式。 B扩展了A,因此它可能具有更多功能。这可能是回顾和阅读多态性的好时机。

答案 7 :(得分:0)

你无法向下施放物体。你可以创建一个

A a1 = new B()

但你无法创建

B b1 = new A()

像每个德国人Shepard都是狗一样简单。所以你可以创建一个新的德国谢泼德狗。

但你不能确定每只狗都是德国谢泼德。因此不支持创建新的德国Shepard型狗。 阅读This