我有以下代码:
class A {
}
class B extends A {
public void fB(){};
}
根据Java规则:
情况1:
B b = new B();
A a = b;
((B)a).fB();
案例二:
A a = new A();
B b = a;
根据 Java 规则,案例 1 可以,案例 2不可以。为什么案例 2不行?这条线((B)a).fB();
实际上做了什么(我的意思是里面发生了什么)?
我有以下代码:
class A {
}
class B extends A {
public void fB(){};
}
根据Java规则:
情况1:
B b = new B();
A a = b;
((B)a).fB();
案例二:
A a = new A();
B b = a;
根据 Java 规则,案例 1 可以,案例 2不可以。为什么案例 2不行?这条线((B)a).fB();
实际上做了什么(我的意思是里面发生了什么)?
为什么案例 1 可以,案例 2 不可以:因为 aDog
是一个Animal
,但不是每个Animal
都是 a 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;
请注意,强制转换对对象没有任何作用;特别是,它不会对对象进行任何类型的转换。强制转换只是告诉编译器“我在这里有这个对象,我比你更清楚它是什么;我希望你把它当作 X 类型而不给我任何错误消息”。
所以在这样的一行中:
Dog doggy = pet2;
编译器会抱怨,因为它不能确定它pet2
实际上是一个Dog
; 它只知道它是一个Animal
- 而不是所有Animal
的 s 都是Dog
s。你可以做一个演员来告诉编译器不要抱怨这个:
// Tell the compiler that you want it to treat pet2 as a Dog
Dog doggy = (Dog)pet2;
但是当你运行程序时,Java 仍然会检查是否pet2
真的是 a Dog
,如果不是,你会得到一个ClassCastException
.
(正如 biziclop 注意到的那样,您标题中的问题与您的意思完全相反)。
好的,想想两个人:医生和工程师。医生可以治疗,工程师可以建造。两者都是人。
现在这是你的例子。
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),但不是每个人都是医生,因为不是每个人都可以治疗。类层次结构也完全相同。子类继承其超类的属性,并可能添加自己的属性。因此,不是任何超类的实例都可以转换为子类。
案例 1 没问题,因为 (B)a 部分您明确告诉编译器:
即使你只知道 a 属于 AI 类型,我也在告诉你它属于 B 类型
因此对象 a 被视为 B 类型
情况 2 不行,因为编译器不能安全地将 b 分配给 a。如果你写的话会被接受
A a = new A();
B b = (B)a;
但它会在运行时抛出异常
假设情况 2 也有效,那么您的编译器将“b”视为“B”类的对象。现在你可以说“b.fb()”。但实际上“b”是“A”的对象(请记住,您将“A”类的对象分配给“b”)。“A”类中没有函数 fb()。你的应用程序崩溃了!!