Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.

Bug 350358

Summary: Deviation from JDK w.r.t. iterating over generic lists with elements of wrong type
Product: [Eclipse Project] JDT Reporter: rene
Component: CoreAssignee: Srikanth Sankaran <srikanth_sankaran>
Status: VERIFIED INVALID QA Contact:
Severity: normal    
Priority: P3 CC: jarthana, rene, srikanth_sankaran, stephan.herrmann
Version: 3.7   
Target Milestone: 3.7.1   
Hardware: PC   
OS: Windows XP   
Whiteboard:

Description rene CLA 2011-06-25 13:36:03 EDT
Build Identifier: 20110615-0604

In Java, it is possible to fill generic lists with elements of the wrong type:

List list1 = new ArrayList();
list1.add(42);
List<String> list2 = new ArrayList<String>();
list2.addAll(list1); // unchecked addAll

Then, iterating over such list2 via

for (Object o : list2) {...}

yields different behavior if compiled with JDT (no exception) and JDK (ClassCastException), respectively.


Reproducible: Always

Steps to Reproduce:
1. Compile/Run the class JDTvsJDK (s. below) within Eclipse (JDT): System.out is "JDT compiler".
2. Compile the class using JDK's 'javac' and run with 'java': System.out is "JDK compiler.


import java.util.ArrayList;
import java.util.List;

public class JDTvsJDK {
	public static void main(String[] args) {
		
		List list1 = new ArrayList();
		list1.add(42);
		
		List<String> list2 = new ArrayList<String>();
		list2.addAll(list1); // unchecked addAll
		
		try {
			// JDT cast Integer to Object
			// JDK cast Integer to String (exception) and then to Object
			for (Object o : list2); 
			System.out.println("JDT compiler");			
		} catch (ClassCastException e) {
			System.out.println("JDK compiler");
		}
	}
}
Comment 1 Stephan Herrmann CLA 2011-06-26 07:41:24 EDT
I could reproduce using javac 1.6.0_22. However, the 1.7 version of javac
shows the same behavior as the JDT compiler (no cast, because the result 
from erased next() (Object) is already good enough for this application).

Do you see scenarii where it is important to actually throw CCE?

The important part is the warning re unchecked conversion which breaks
type safety and after which CCE *may* occur, but why should we force
an unnecessary CCE?
Comment 3 Srikanth Sankaran CLA 2011-06-30 02:48:15 EDT
Agree with comment#1.

Per 14.14.2, the enhanced for loop of the form:

for ( VariableModifiersopt Type Identifier: Expression) Statement;

is equivalent to:

for (I #i = Expression.iterator(); #i.hasNext(); ) {
VariableModifiersopt Type Identifier = #i.next();
Statement;
}

(where # denotes erasure), Since in this context the
LHS and RHS are of type Object, the cast seems unnecessary.

Confirmed that eclipse behavior matches JDK 7b142.

Closing as INVALID.
Comment 4 Jay Arthanareeswaran CLA 2011-08-25 06:16:29 EDT
Verified for 3.7.1 RC2.