Reputation: 3789
Given the following piece of code:
public class ClassCastTest {
private static class GenericHolder<T> {
private T object;
public GenericHolder(Object object) {
this.object = (T) object;
System.out.println(getObject());
}
public T getObject() {
return object;
}
}
public static void main(String[] args) {
GenericHolder<String> foo = new GenericHolder<>(3l);
System.out.println(foo.getObject());
}
}
Why does Java throw a ClassCastException in the second line of the main-method instead of the second line of the GenericHolder?
Upvotes: 3
Views: 540
Reputation: 37645
In addition to Louis' answer, it's useful to point out that casting to a T
by writing (T)
does "do something" in the case that T
is bounded. For example, if you write
private static class GenericHolder<T extends CharSequence>
instead, then the line
this.object = (T) object;
does throw a ClassCastException
, because you can't cast a Long
to a CharSequence
(note the question says 3l
not 31
). However it won't attempt to cast to a String
at that point because the type T
is not known at runtime.
Upvotes: 2
Reputation: 198024
Because of the way generics are implemented in the language, your cast to (T)
doesn't actually do anything. It's only when you use a generic type in a way that actually gets out a concrete type -- here, System.out.println
expects a String
and it does the cast to get it -- that the runtime actually does any casting.
As far as the Java runtime is concerned, there's no difference between a GenericHolder<String>
and a GenericHolder<Integer>
; they both hold an Object
. Java just inserts casts anywhere you get a concrete type out of a generic type.
Research type erasure for more details.
Upvotes: 6