+2  A: 
T.J. Crowder
the String part is lost at runtime (erasure), so no conversion actually takes place. But it is very wrong to do it the way he did.
Bozho
@Bozho: Clearly not in the `Iterator<E>` implementation. When I compile his code with the Sun Java 6 compiler (1.6.0_20) on Linux and run it, I reliably get the `ClassCastException`.
T.J. Crowder
I ran it and it does not throw an exception :), 1.6.0_20, Windows XP
Bozho
Well it doesn't throw a ClassCastException because I'm using Object to iterate over the list.
robert
@robert: But you're doing that with a `Iterator<String>`.
T.J. Crowder
@Bozho: Don't know what to tell you. Sun's Java 6 compiler and runtime, on Linux, throw the exception.
T.J. Crowder
It isn't throwing an Exception on Linux 1.6.0_20 neither. It only throws one when you try to alter the type in the for control from Object to String for example.
Octavian Damiean
@Octavian: *"It isn't throwing an Exception on Linux 1.6.0_20 neither."* Yes, it is, for me. If it isn't for you, I wonder what's different?
T.J. Crowder
@Bozho: Hmm...Compiling on 1.6.0_21 (for me) inserts a `checkcast <java/lang/String>` instruction, which causes the exception.
Tim Stone
@Octavian What compiler are you using?
robert
@ T.J. Crowder: I have no clue what the difference is. I can run it without any exceptions for as many times as I try.
Octavian Damiean
@robert: 1.6.0_20
Octavian Damiean
This is a rather interesting discussion, but I think we all agree what is wrong with the code and what has to be fixed :)
Bozho
@Octavian: Yes, but is it Sun's compiler? Or the OpenJDK?
T.J. Crowder
@robert: Sorry Sun's yes.
Octavian Damiean
@Bozho: *"...but I think we all agree what is wrong with the code and what has to be fixed"* Completely. :-)
T.J. Crowder
+1  A: 

I can't reproduce it either, but I spot the following mistakes that must be corrected:

  • make getObjects() return List<Integer>, rather than a raw type
  • Don't expect List<String>, but a List<Integer> instead
  • When iterating, loop for (Integer o : list)
Bozho
A: 

The problem is the method static List getObjects() { returns a generic (non parameterised) List. And you assign it to List<String>. This line should give a compiler warning, and that should have signalled a problem.

Nivas
A: 

This part :

List<String> list = getObjects();
for (Object o : list) { // ClassCastException?
    System.out.println(o);
}

Will be simplified as

List<String> list = getObjects();
for (Iterator<String> iterator = list.iterator(); iterator.hasNext();) {
    Object o = iterator.next();
    System.out.println(o);
}

But the implementation of Iterator will try to cast when calling the next() method the content send by the Iterator in a String.

That's why you have a CCE.

Solutions :

Either use generics everywhere or don't use them, but it's really important to be consistant. If you had returned a List<Integer> or a List<? super Integer> you would have seen this problem at compilation time.

Colin Hebert
I think you meant `Iterator<String>`, not `Iterator<List>`.
T.J. Crowder
@T.J. Crowder, Yes you're right (and I'm tired...)
Colin Hebert