Java 为什么下面的代码会给出一个classcast异常?

Java 为什么下面的代码会给出一个classcast异常?,java,inheritance,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 exte

下面给出一段代码:

//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();
instanceof运算符为true,因此B是类a的对象。 但为什么在将A转换为B时,即使B是A的子类型,它也会给出ClassCastException呢? 新A;根本不是B

这和你说的一样,每种动物都是猫,没有例外。但事实并非如此

但是,将B转换为A是正确的,因为每只猫都是动物,没有例外:

A a = (A) new B();

B是A的一个正确的例子。但是A不是B的一个实例。这就是为什么会出现异常。

B B=B新的A;是错误的语句导致A不继承B;相反,B继承了A,允许这样的铸造是不安全的

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的实例。但稍后我们可以尝试从b引用调用setX

b.setX(1);
这应该很好,因为并没有强制转换异常,所以B引用中的对象应该能够支持此调用。 您认为JVM在下一行应该如何反应?这样的代码应该被允许吗

不,base A不知道应该如何为setX执行哪些代码,即使它知道,它也没有int x字段来存储它的数据。所以为了防止这种情况,JVM抛出ClassCastException

2你可以这样说:好的,但我的B没有改变接口,它没有给A添加任何新的内容。你是对的,但在这种情况下允许强制转换也是危险的,因为当从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();

也将起作用,因此我们可以无限制地添加到赛车中,这不是我们想要的。

B是a的子类,不能将a转换为B。事实上,也许新A对象的具体类是另一个类,而不是一个扩展了A的C类。所以你不能肯定A是B的实例。

B类型的对象可以转换为A类型的变量,但不能反过来。B扩展了A,因此它可能具有更多功能。这可能是一个回过头来阅读多态性的好时机。

您不能向下投射对象。您可以创建一个

a1=新的B

但是你不能创建一个

B b1=新的A

这很简单,就像每个德国牧羊犬都是狗一样。所以你可以创造一个新的德国谢泼德狗

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

LimitedSpeedCar lsc = (LimitedSpeedCar) new Car();