为什么超类对象不能在Java中隐式转换为子类对象?

我有以下代码:

class A { } class B extends A { public void fB(){}; } 

根据Java规则:

情况1:

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

案例2:

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

根据Java规则,案例1 还可以 ,案例2 不行 。 为什么案例2 不行 ? 这一行((B)a).fB(); 实际上(我的意思是里面发生了什么)?

为什么案例1没问题,案例2不行:因为DogAnimal ,但不是每个Animal都是Dog

 class Animal { } class Dog extends Animal { } class Cat extends Animal { } Dog fifi = new Dog(); Cat tommy = new Cat(); // OK because Dogs and Cats are Animals Animal pet1 = fifi; Animal pet2 = tommy; // Not OK because an Animal is not always a Dog Dog doggy = pet2; 

请注意,转换对对象没有任何作用; 特别是,它不会对对象进行任何类型的转换。 Casting只告诉编译器“我这里有这个对象,我比你知道的更好;我希望你把它当作X型而不是给我任何错误信息”。

所以在这样一行:

 Dog doggy = pet2; 

编译器会抱怨,因为它不能确定pet2实际上是一只Dog ; 它只知道它是Animal – 并不是所有Animal都是Dog 。 你可以做一个演员来告诉编译器不要抱怨这个:

 // Tell the compiler that you want it to treat pet2 as a Dog Dog doggy = (Dog)pet2; 

但是当你运行程序时,Java仍然会检查pet2是否真的是一个Dog ,如果不是,你会得到一个ClassCastException

(你的标题中的问题与你的意思完全相反,正如biziclop注意到的那样)。

好吧,想想2个人:医生和工程师。 医生可以治疗,工程师可以建立。 两人都是人。

现在这是你的例子。

 Person p = new Person(); // somebody that does not know to do anything special. Doctor d = (Doctor)p; // do you think that casting makes person that does not know anything to be a doctor? 

你是否想被被“铸造”成为医生的人对待你更喜欢真正的医生?

我相信答案很清楚。 每个医生都是一个人(案例1)但不是每个人都是医生,因为不是每个人都可以治疗。 完全相同也与类层次结构相关。 子类inheritance其超类的属性,并可能添加自己的属性。 因此,不能将任何超类实例强制转换为子类。

情况1是可以的,因为(B)是您明确告诉编译器的一部分:

即使你只知道a型AI也告诉你它是B型

所以对象a被视为类型B

情况2不正常,因为编译器无法安全地将b分配给a。 如果你写的话会被接受

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

但它会在运行时抛出exception

假设情况2也在工作,那么您的编译器将“b”视为类“B”的对象。 现在你可以说“b.fb()”。 但实际上“b”是“A”的对象(记住你将类“A”的对象分配给“b”)。 类“A”中没有函数fb()。 你的应用程序崩溃了!!