简体   繁体   English

为什么以下代码会给出类广播异常?

[英]Why does the following code give a classcast exception?

Given below piece of code: 给出下面的代码:

//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. The instanceof operator gives true so B is a object of class A . instanceof运算符的值为true,因此B是类A的对象。
  2. But why while casting A to B its gives ClassCastException even though B is an sub-type of A ? 但是,为什么在将A强制转换为B ClassCastException给出ClassCastException即使BA的子类型呢?

new A(); is simply not B . 根本不是B

It's the same as you were saying that "Every Animal is a Cat with no exceptions". 就像您说的“每个动物都是猫,没有例外”一样。 Which is not true. 这是不对的。

However, casting B to A would be correct (because every Cat is an Animal, with no exceptions): 但是,将B强制转换为A是正确的(因为每个猫都是动物,没有例外):

A a = (A) new B();
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

B is an instance of A that is right. B是正确的A的实例。 But A is not an instance of B. That's why you get the exception. 但是A不是B的实例。这就是为什么您会得到例外。

B b = (B) new A(); is the wrong statement cause A doesn't inherits B ; 是错误的陈述,因为A不继承B ; rather B inherits A 而是B继承了A

Allowing such casting would not be safe for few reasons. 出于种种原因,允许进行此类铸造并不安全。

1) Lets say that you added in your B additional method of field which A doesn't have like 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;
    }
}

Now lets assume that this casting will work 现在让我们假设这种转换将起作用

B b = (B) new A();

So b will hold instance of A . 因此b将持有A实例。 But later we can try invoking setX from B reference 但是稍后我们可以尝试从B参考调用setX

b.setX(1);

which should be fine because there was no casting exception so object from B reference should be able to support this call. 这应该没问题,因为没有强制转换异常,因此B引用中的对象应该能够支持此调用。
What do you think, how should JVM react on this next line? 您如何看待,JVM应该如何对下一行做出反应? Should such code be allowed? 应该允许这样的代码吗?

No, base A doesn't know how which code should be executed for setX and even if it knew it, it doesn't have int x field to store its data. 不,基A不知道应该如何为setX执行哪个代码,即使知道,它也没有int x字段来存储其数据。 So to prevent such situations JVM throws ClassCastException. 因此,为防止此类情况,JVM抛出ClassCastException。


2) You can say that: " OK, but my B doesn't change interface, it doesn't add anything new to A ". 2)您可以说:“ 好,但是我的B不会更改接口,它不会为A添加任何新内容 ”。 You are right, but allowing casting in this case is also dangerous, because while invoked methods from B you should be able to expect that they will behave in a way described in B class, or its subclasses. 没错,但是在这种情况下允许强制转换也是危险的,因为从B调用方法时,您应该可以期望它们将以B类或其子类中描述的方式运行。

Lets say that we are building racing game and we have classes 可以说我们正在开发赛车游戏,并且有课程

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

Now you want to create racing track only for cars with limited speed. 现在,您只想为速度有限的汽车创建赛道。 So you are creating LimitedSpeedCar[] array to store only cars with limited speed. 因此,您要创建LimitedSpeedCar[]数组,以仅存储速度受限的汽车。 But guess what, because 但是你猜怎么着,因为

B b = (B) new A();

works fine it means that 正常工作意味着

LimitedSpeedCar lsc = (LimitedSpeedCar) new Car();

will also work so we can add to our race car without limits which is not what we wanted. 也将起作用,因此我们可以不受限制地添加到赛车中,这不是我们想要的。

B is a subclass of A , you cannot cast A to B . BA的子类,不能将A强制转换为B In fact, maybe the concrete class of the new A Object is another class than B (let say a class C that extends A ). 实际上,也许新A Object的具体类是B以外的另一个类(比方说,扩展A的类C )。 So you cannot affirm that A is an instance of B . 因此,您不能肯定AB的实例。

An object of type B can be cast to variable of type A but not the other way around. 可以将类型B的对象强制转换为类型A的变量,但不能强制转换为其他类型。 B extends A so it could potentially have more functionality. B扩展了A,因此它可能具有更多功能。 This might be a good time to go back and read up on polymorphism. 这可能是回头阅读多态性的好时机。

You can't down cast an object. 您不能向下投射对象。 You can create a 您可以创建一个

A a1 = new B() . A a1 = new B()

But you can't create a 但是您不能创建一个

B b1 = new A()

It's simple like every German Shepard is a Dog. 就像每个德国谢泼德都是狗一样,这很简单。 So you can create a new German Shepard dog. 因此,您可以创建一条新的德国Shepard狗。

But you can't be sure that every Dog is a German Shepard. 但是您不能确定每只狗都是德国谢泼德犬。 Hence creating a new German Shepard of type dog is not supported. 因此,不支持创建新的dog类型的德国Shepard。 Read This 阅读

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM