Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/dart/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 当施法子类等于超类时,施法失败_Java_Casting_Classcastexception - Fatal编程技术网

Java 当施法子类等于超类时,施法失败

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

我有点搞不清楚为什么下面的代码不起作用,并抛出ClassCastException:

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”关系,但查看类继承树。其他语言的行为可能不同。。。