JDK-6545698 : Erroneous method typing for parametrized inner class methods in foreach syntax.
  • Type: Bug
  • Component: tools
  • Sub-Component: javac
  • Affected Version: 6
  • Priority: P4
  • Status: Closed
  • Resolution: Not an Issue
  • OS: windows_xp
  • CPU: x86
  • Submitted: 2007-04-13
  • Updated: 2010-04-04
  • Resolved: 2007-05-15
Related Reports
Relates :  
Description
FULL PRODUCT VERSION :
java version "1.6.0_01"
Java(TM) SE Runtime Environment (build 1.6.0_01 b06)
Java HotSpot(TM) Client VM (build 1.6.0_01-b06, mixed mode, sharing)

ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows XP [Version 5.1.2600]

A DESCRIPTION OF THE PROBLEM :
Compile-time typing checks for a method with a parametrized return type was observed to fail when the method in question appears in an inner class of the calling method's class and is referenced from the for iterator (foreach) syntax.

In other words -
for (String paramName : col.getParameterNames()) {}

will fail the check, whereas

for (Iterator<String> it = col.getParameterNames().iterator(); it.hasNext();) {}

will pass.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Compiling the included test case should reproduce the problem.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The test case is expected to compile properly.
ACTUAL -
The test case fails to compile with the error included in this report.


ERROR MESSAGES/STACK TRACES THAT OCCUR :

C:\Documents and Settings\David.Trombley\Desktop\dispatch\DIS\src\dis\schema\Test.java:15: incompatible types
found   : java.lang.Object
required: java.lang.String
            for (String s : it.someSet()) {}
Note: C:\Documents and Settings\David.Trombley\Desktop\dispatch\DIS\src\dis\schema\Test.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
1 error
BUILD FAILED (total time: 1 second)


REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
---- The following will not compile ----

import java.util.*;

public class Test {
Vector<InnerTest> inners = new Vector<InnerTest>();

    public class InnerTest<T> {
       public Set<String> someSet() { return (new HashMap<String,String>()).keySet(); }
    }
    
    public Test() {
        for (InnerTest it : inners) {
            for (Iterator<String> iter = it.someSet().iterator(); iter.hasNext();) {} // *
            for (String s : it.someSet()) {}
        }
    }
}

---- However, the following compiles ----

import java.util.*;

public class Test {
Vector<InnerTest> inners = new Vector<InnerTest>();

    public class InnerTest {
       public Set<String> someSet() { return (new HashMap<String,String>()).keySet(); }
    }
    
    public Test() {
        for (InnerTest it : inners) {
            for (Iterator<String> iter = it.someSet().iterator(); iter.hasNext();) {} // *
            for (String s : it.someSet()) {}
        }
    }
}
---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
Use the explicit iterator syntax on the line with the asterisk in comment instead of the "foreach" syntax.

Comments
EVALUATION This is not a bug. The program is not correct. Change: for (InnerTest it : inners) { to for (InnerTest<?> it : inners) {
15-05-2007