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 justObject
), but this behavior is undefined as far as I understand from the JLS. Try runningjavap
on your two.class
files and looking at the code right around thatfor
loop (probably right after aninvokeinterface
call toIterator.next()
).