Bug 209779 - [1.5][compiler] javac mismatch in cast behaviour in a for loop
Summary: [1.5][compiler] javac mismatch in cast behaviour in a for loop
Status: VERIFIED INVALID
Alias: None
Product: JDT
Classification: Eclipse Project
Component: Core (show other bugs)
Version: 3.3.1   Edit
Hardware: PC Windows XP
: P3 normal (vote)
Target Milestone: 3.4 M4   Edit
Assignee: Philipe Mulet CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2007-11-14 07:19 EST by Christophe Boutter CLA
Modified: 2008-05-30 08:09 EDT (History)
1 user (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Christophe Boutter CLA 2007-11-14 07:19:59 EST
Consider the followoing example:
----
import java.util.ArrayList;
import java.util.List;
  
public class ForEachTest {
  public static void main(String[] args) {
    final List<String> stringList = new ArrayList<String>();
    stringList.add("test1");
    stringList.add("test2");
    ((List) stringList).add(new Integer(1000));

    for (Object obj : stringList) { // line 11
      System.out.println(obj);
    }
  }
}
----------
The latest Eclipse 3.3.1.1 compiler compiles it and the program runs fine with output:
test1
test2
1000

With javac (for example version 1.6.0_01-b06 under Windows) the program compiles but the program fails with output:
test1
test2
Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
at ForEachTest.main(ForEachTest.java:11)

The javac makes a cast on the next iterator in the bytecode whereas the eclipse compiler ommits the cast. The Java language spec doesn't say anything about it, but it's irritating.
Comment 1 Philipe Mulet CLA 2007-11-14 12:49:10 EST
Feels like we are doing the right thing. We would issue the ClassCastException if code was performing:

    for (String str : stringList) { // line 11
      System.out.println(str);
    }

But since the code is manipulating the list as objects, we do not insert cast to String checks.

Interestingly, if you write instead:
import java.util.ArrayList;
import java.util.List;

public class X {
  public static void main(String[] args) {
    final List<String> stringList = new ArrayList<String>();
    stringList.add("test1");
    stringList.add("test2");
    ((List) stringList).add(new Integer(1000));

    Object o = stringList.get(2);
  }
}

No ClassCastException is generated any longer, from javac output.
Strictly speaking, I don't see why any would be different from the other.
By using an Object variable in the foreach loop, the #println(Object) is selected, and thus no String cast should be required.

Comment 2 Christophe Boutter CLA 2007-11-15 02:15:01 EST
You're right there should be no difference between both codes since the return type of both the next iterator and the get method is String in our example.

But by decompiling the output of the javac one sees the cast:
for(Iterator iterator = arraylist.iterator(); iterator.hasNext(); System.out.println(s))
            s = (String)iterator.next();

--

Object obj = arraylist.get(2);
-------------

That's not very consistant from the javac. I don't know if it's y bug from Eclipse compiler or from the java compiler but I wanted to report the mismatch between both.
Comment 3 Philipe Mulet CLA 2007-11-15 04:40:22 EST
Yes, the inserted cast is visible in bytecode.
Knowing the mismatch is good, I am investigating whether there would be a secret entry in the spec which would explain the difference.
So far, I am leaning towards a javac bug... but this is still premature.
Comment 4 Philipe Mulet CLA 2007-11-15 05:58:37 EST
Added GenericTypeTest#test1219
Comment 5 Philipe Mulet CLA 2007-11-20 06:25:36 EST
Got confirmation from spec master that our behavior is the proper one.
This is a javac bug which you should report to them.

Closing as INVALID since our behavior is valid.
Comment 6 Christophe Boutter CLA 2007-11-20 07:23:00 EST
In his Post on dev.java.net (http://forums.java.net/jive/thread.jspa?messageID=246154#246154) Nishanth Sastry tells us that the behavior of the javac is correct and eclipse should throw an Exception. We will look at it and maybe write another comment here.
Comment 7 Kent Johnson CLA 2007-12-11 11:39:28 EST
Verified for 3.4M4 using build I20071210-1800.
Comment 8 Maxime Daniel CLA 2008-05-30 08:09:16 EDT
As reported in bug 232487, javac bug has been identified since as http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6500701.