This is a narrow-down example of a case I came across.
Take a look at the code below:
class Holder<T> {
private T t;
public Holder(T t) {
this.t = t;
}
public T getValue() {
return t;
}
}
public class FooMain {
private static Object newHolder() {
return new Holder<Integer>(3);
}
public static void main(String args[]) {
Holder<String> hs = (Holder<String>) newHolder(); // line-18
String s = hs.getValue(); // line-19
}
}
What spooked me is that the inevitable ClassCastException
gets thrown on line-19 and not on line-18 !
Therefore, having an object in your code that's of type Holder<String>
is not enough to guarantee that getValue
will return a String
. You also have to examine how this object was constructed!
I understand that Type Erasure plays a role here but I am not sure how wide the implications of the above are. In my particular case the newHolder
-corresponding method is defined in an external library and returns java.lang.Object
so I have to do these casts.