Java 当施法子类等于超类时,施法失败
我有点搞不清楚为什么下面的代码不起作用,并抛出ClassCastException:Java 当施法子类等于超类时,施法失败,java,casting,classcastexception,Java,Casting,Classcastexception,我有点搞不清楚为什么下面的代码不起作用,并抛出ClassCastException: Person superPerson = new Person("marc", 18); PersonOverwritten subPerson = (PersonOverwritten) superPerson; System.out.println(subPerson); 其中子类与超级类相同: public class PersonOverw
Person superPerson = new Person("marc", 18);
PersonOverwritten subPerson = (PersonOverwritten) superPerson;
System.out.println(subPerson);
其中子类与超级类相同:
public class PersonOverwritten extends Person {
public PersonOverwritten(String nome, int idade) {
super();
}
}
当然,如果他们来自不同的类型,它应该会失败,但是,为什么这不起作用呢?您不能将
新人()
强制转换为个人重写
尽管编译器会让它通过,但运行时会检测到类型Person
太宽,无法放入personoverwrited
,这就是为什么会出现ClassCastException
请注意:如果您有同一父类的不同、不相关的子类,则会发生类似的异常:
public class AnotherPersonOverwritten extends Person {}
以下内容也不正确:
Person subPerson = new AnotherPersonOverwritten();
PersonOverwritten personOverwritten = (PersonOverwritten) new subPerson;
//class cast exception
如何避免这种情况:确保正在转换的对象的运行时类(在本例中,与new
关键字一起使用的类)与正在转换对象的类相同或是该类的子类。下面是一个简单的示例来说明。想象一下,personoverwrited
看起来是这样的:
public class PersonOverwritten extends Person {
public PersonOverwritten(String nome, int idade) {
super();
}
public void pickupSticks() {}
}
Person person = new PersonOverwritten("marc", 18);
((PersonOverwritten)person).pickupSticks();
很明显,你是做不到的
Person superPerson = new Person("marc", 18);
PersonOverwritten subPerson = (PersonOverwritten) superPerson;
subPerson.pickupSticks();
因为分配给子角色的对象没有拾取方法
编译器允许您编写这样的代码的原因是,有朝一日您可能会想做这样的事情:
public class PersonOverwritten extends Person {
public PersonOverwritten(String nome, int idade) {
super();
}
public void pickupSticks() {}
}
Person person = new PersonOverwritten("marc", 18);
((PersonOverwritten)person).pickupSticks();
在这种情况下,当然不会出现运行时错误,因为您分配给person
的对象支持扩展接口。在Java1.5中引入泛型之前,经常会看到类似的情况,当您访问所有集合时,它们都返回Object
更新
更详细地说,Java使用类型来确定对象履行的契约,而不是直接检查属性。它不使用duck类型,比如Python。编译器将允许您将Person
转换为personoverwrited
,因为这是可能的。运行时将禁止您使用实际的Person
对象作为personoverwrited
,因为根据Java,它不能实现接口。将父类的对象分配给其子类引用变量将失败。正如评论中提到的图灵85和格特曼
请看以下代码:
Dog dog = new Dog();
// Cat cat = new Cat();
// Animal animal = cat;
Animal animal = dog; // here upcasting is automatic
if(animal instanceof Dog) // only if the animal is of type Dog
Dog dogDup = (Dog) animal; // manual downcasting
/*
Animal animal = new Animal();
Dog dog = (Dog) animal; // this won't work
*/
请参阅全文
要防止代码引发运行时异常,请像下面这样使用instanceof运算符
Person superPerson = new Person("marc", 18);
if(superPerson instanceof PersonOverwritten) // in this case it's "false"
PersonOverwritten subPerson = (PersonOverwritten) superPerson;
[有关更多详细信息,请参阅stackoverflow问题]
希望这会有帮助 因为并不是每只狗都是猎犬,personoverwrited
是人
,但人
不一定是人
,在这种情况下,就不一定了。还有一个问题,在《语言规范》的文章中得到了回答。这种类型的转换是被调用的,并且有非常明确的规则来指导哪些案例有效以及为什么有效。感谢您的回答,我得到了这样一个概念,即人不一定是一个写过的人,但是这个案例是并且确实有相同的方法,那么为什么它仍然不起作用呢?因为Java没有比较内容来决定结果“is-a”关系,但查看类继承树。其他语言的行为可能不同。。。