Check out this Java 5 code:
public static <T> List<T> extractSomeStuff(Collection collection) {
List<T> extractedStuff = new ArrayList<T>(collection.size());
for (Object element : collection) {
extractedStuff.add((T) element);
}
return extractedStuff;
}
public static void someMethodThatIsRunning() {
List integers = new ArrayList();
integers.add(1); integers.add(2); integers.add(500);
List longs = extractSomeStuff(integers);
long notAnInteger = longs.get(0);
}
Will there be a ClassCastException thrown? Yes.
Do you know what line it will be on?
Possibly not where you expect. Java Generics are designed to be able to easily compile down to older Java versions. In essence, I could write a program in Java 5 and make it target a Java 1.4 JVM so I can run on older machines that haven’t upgraded their JVM. The way this works is by a process called type erasure which happens at compile time. Any uses of Generics are checked to make sure the types are in agreement, and after they are validated, all type information is erased.
At any point where you actually need to the typed object, it will be replaced with a cast at runtime, so for List, when T get(int index) is called, the result gets cast to T.
The result is that the ClassCastException happens at long notAnInteger = longs.get(0); and not at extractedStuff.add((T) element); because that type information is erased.
The moral of the story is don’t cast objects with Generic types unless you really know what you’re doing. 90% of the time, you’re probably presenting a user with a method contract that you won’t be able to fulfill, and the user will only find out several lines later in their code when they realize that their collection is filled with objects they didn’t expect.
Published under the Attribution-Noncommercial 3.0 Unported license. To request another license, ask me.code · example · generics · java

Dan Tasse · July 15, 2010 at 2:12 am
Is there supposed to be another T there somewhere? Like:
public static List extractSomeStuff
or something? Because where does that T come from? Also, I see no reason why the ClassCastException should be thrown anywhere other than where it is.
Or maybe I understand generics less than I thought…
Dan Tasse · July 15, 2010 at 2:14 am
Aha! There should be another <T> somewhere: it got HTML-tagged-out!
Admin comment by yincrash · July 15, 2010 at 9:05 am
Thank you, Dan Tasse. WordPress should have some warnings when it filters out > and <
Admin comment by yincrash · July 15, 2010 at 9:44 am
If you’re using a language that doesn’t perform type erasure, like C++, which I believe creates a new runtime class every time you give a template a new type, the runtime error should happen at the
(T) elementline. To be honest, I’m surprised there isn’t a compiler warning for this.