简体   繁体   English

在转换子类等于超类时,强制转换失败

[英]Cast fails when casting a sub class equals to the super class

I am a little confuse on why the below code doesn't work and throw a ClassCastException: 我有点混淆为什么下面的代码不起作用并抛出ClassCastException:

Person superPerson = new Person("marc", 18);        

        PersonOverwritten subPerson = (PersonOverwritten) superPerson;      
        System.out.println(subPerson);

Where the subclass is the same as the super: 子类与super相同的位置:

public class PersonOverwritten extends Person {

    public PersonOverwritten(String nome, int idade) {
        super();
    }

}

Of course it should fail if they are from different types, but, why this doesn't work? 当然,如果它们来自不同类型,它应该会失败,但是,为什么这不起作用?

Here's a simple example to illustrate. 这是一个简单的例子来说明。 Imagine that PersonOverwritten looked like this: 想象一下, PersonOverwritten看起来像这样:

public class PersonOverwritten extends Person {
    public PersonOverwritten(String nome, int idade) {
        super();
    }
    public void pickupSticks() {}
}

Very clearly you would not be able to do 很明显,你无法做到

Person superPerson = new Person("marc", 18);        
PersonOverwritten subPerson = (PersonOverwritten) superPerson;
subPerson.pickupSticks();

because the object assigned to subPerson does not have the pickupSticks method. 因为分配给subPerson的对象没有pickupSticks方法。

The reason that the compiler allows you to write code like that, though, is that you might one day want to do something like this: 编译器允许你编写这样的代码的原因是,有一天你可能想做这样的事情:

Person person = new PersonOverwritten("marc", 18);        
((PersonOverwritten)person).pickupSticks();

In this case, there will of course not be a runtime error, because the object that you have assigned to person does support the extended interface. 在这种情况下,当然不会出现运行时错误,因为您分配给person的对象确实支持扩展接口。 A very common place to see something like that was before generics were introduced in Java 1.5, and all the collections returned Object when you accessed them. 在Java 1.5中引入泛型之前,看到类似内容的一个非常常见的地方是,当您访问它们时,所有集合都返回了Object

Update 更新

To elaborate a bit, Java uses types to determine the contract that an object fulfills, rather than a direct inspection of the attributes. 为了详细说明,Java使用类型来确定对象实现的契约,而不是直接检查属性。 It does not use duck-typing, like say Python. 它不使用duck-typing,比如说Python。 The compiler will allow you to cast Person to PersonOverwritten because it might be possible. 编译器允许您将PersonPersonOverwritten因为它可能是可能的。 The runtime will forbid you from using an actual Person object as a PersonOverwritten because, according to Java, it does not fulfill the interface. 运行时将禁止您将实际的Person对象用作PersonOverwritten因为根据Java,它不支持接口。

You cannot cast new Person() to PersonOverwritten . 您不能将new Person() PersonOverwrittenPersonOverwritten

Although the compiler will let this pass, the runtime will detect that the type Person is too broad to fit into PersonOverwritten , which is why you get that ClassCastException . 虽然编译器会让这个传递,但是运行时会检测到Person类型太宽PersonOverwritten适合PersonOverwritten ,这就是你得到ClassCastException


Just a side note: A similar exception would occur if you had a different, unrelated subclass of the same parent: 只是旁注:如果您拥有同一父级的不同,不相关的子类,则会发生类似的异常:

public class AnotherPersonOverwritten extends Person {}

The following is also incorrect: 以下内容也不正确:

Person subPerson = new AnotherPersonOverwritten();
PersonOverwritten personOverwritten = (PersonOverwritten) new subPerson;
//class cast exception

How do you avoid this : Make sure that the runtime class of the object being cast (the class with which the new keyword is used, in this case) is the same as or the subclass of the class to which the object is being cast. 如何避免这种情况 :确保要转换的对象的运行时类(在这种情况下使用new关键字的类)与要转换对象的类的子类相同。

Assigning an object of parent class to its subclass reference variable will fail. 将父类的对象分配给其子类引用变量将失败。 As #Turing85 and #rgettman mentioned in the comment. 正如#Turing85#rgettman在评论中提到的那样。

Look at the following code: 看下面的代码:

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
*/

See the full article here 请参阅此处的完整文章

To prevent your code from throwing runtime exception, use instanceof operator like this 要防止代码抛出运行时异常,请像这样使用instanceof运算符

Person superPerson = new Person("marc", 18);
if(superPerson instanceof PersonOverwritten) // in this case it's "false"
    PersonOverwritten subPerson = (PersonOverwritten) superPerson;

[for more details refer this stackoverflow question] [有关详细信息,请参阅 stackoverflow问题]

Hope this will help! 希望这会有所帮助!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM