sylleryum
sylleryum

Reputation: 140

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:

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

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

Where the subclass is the same as the 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?

Upvotes: 2

Views: 175

Answers (3)

Mad Physicist
Mad Physicist

Reputation: 114250

Here's a simple example to illustrate. Imagine that PersonOverwritten looked like this:

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.

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. 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.

Update

To elaborate a bit, Java uses types to determine the contract that an object fulfills, rather than a direct inspection of the attributes. It does not use duck-typing, like say Python. The compiler will allow you to cast Person to PersonOverwritten because it might be possible. The runtime will forbid you from using an actual Person object as a PersonOverwritten because, according to Java, it does not fulfill the interface.

Upvotes: 4

S.Negi
S.Negi

Reputation: 51

Assigning an object of parent class to its subclass reference variable will fail. As #Turing85 and #rgettman mentioned in the comment.

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

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]

Hope this will help!

Upvotes: 0

ernest_k
ernest_k

Reputation: 45309

You cannot cast new Person() to PersonOverwritten.

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.


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.

Upvotes: 1

Related Questions