I hope you can assist me on this matter.
I've been looking for answers to this question but all I could find was related to generic type usage or general instructions about reflection.
Say we have a parent class and a child class which extends that parent. So, see below:
Parent v = new Child();
If I make v.getClass()
it returns Child
. However, if I make v.getClass().cast()
it returns an object from type Parent
.
Anyone knows why it happens? I also took a look at the Java API documentation and couldn't find a reason...
Thanks for any thoughts.
There's an important distinction between what the runtime type of an object and the compile-time type of a variable or expression is. The compile-time type of an expression can only be determined from the compile-time types of its components. The runtime types of objects that are the values of these expressions may be determined from the runtime types of the parameters of the expression, as long as they are compatible with the compile-time types.
To illustrate this, in your specific code sample:
v
has the compile-time type Parent
, but the runtime type of the value assigned to it will be Child
.v.getClass()
will have the compile-time type Class<? extends Parent>
(a class object representing either the Parent
type or one of its subclasses.). Its value at runtime will be Child.class
which is of type Class<Child>
.v.getClass().cast(obj)
will have the compile-time type Parent
. It's runtime type will be the runtime type of obj
, because its runtime value will, in fact, be obj
itself. (That is, if obj is of a type that's assignable to a variable of type Child
, otherwise cast()
will throw a ClassCastException
)I've been looking for answers to this question but all I could find was related to generic type usage or general instructions about reflection.
You receive a Class<Parent>
as that is the compile time type.
//compiletime v is of type Parent
Parent v = new Child();
//The class of a Parent object is either the Parent class or a child Class
Class<? extends Parent> cls = v.getClass();
//The return type of cast is the at compile time known upper bound, here it is
//Parent, which is true since every Child object is also a Parent object.
cls.cast(...);
//Note that this will throw a runtime exception, since it will perform a
//cast to child at runtime. The cast uses the Child class at runtime and
//fails for other instances of Parent.
cls.cast(new Parent());
Here a simplified example for what you can use it.
class Test<T>{
public Test(Class<T> cls){clazz = cls;}
ArrayList<T> list = ...;
Class<T> clazz;
void add(Object o){
list.add((T)o);//Cast does nothing at runtime
list.add(clazz.cast(o)); //casts o to T
}
}
A normal cast in the form (T)o does not work in java as the generic type T is not known at runtime. The jvm only sees the upper bound (Object) cast which never fails. Using the cast method with a reference to the actual class instead is a workaround for this.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With