Reputation: 140
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
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
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
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