The following code
import java.util.*;
import java.io.*;
@SuppressWarnings("unchecked")
List<Serializable> list = (List<Serializable>) (List<?>)
Collections.singletonList(new Object());
for (Object el : list) { // -> ClassCastException
System.out.println(el);
}
is correct Java (even though the code is suspicious). Using javac
and java
6 it throws
Exception in thread "main" java.lang.ClassCastException: java.lang.Object cannot be cast to java.io.Serializable
while it runs without error when using javac
and java
7.
Is it a language change, fixed bug or a hidden feature?
(Note: Code compiled with Eclipse runs without error on all Eclipse versions checked - Helios to Kepler.)
You're polluting the heap by adding your raw Object
to the collection (which you're having to do the cast dance to make happen). It's not technically illegal, but it is a bug.
When you are pulling the value out of your implicit iterator, the Java 6 compiler appears to be casting immediately, while the Java 7 compiler isn't. It's more efficient not to cast to Serializable
if it doesn't need to (since the holding variable is just Object
), but this behavior is undefined as far as I understand from the JLS. Try running javap
on your two .class
files and looking at the code right around that for
loop (probably right after an invokeinterface
call to Iterator.next()
).