Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
Bug 350358 - Deviation from JDK w.r.t. iterating over generic lists with elements of wrong type
Summary: Deviation from JDK w.r.t. iterating over generic lists with elements of wrong...
Status: VERIFIED INVALID
Alias: None
Product: JDT
Classification: Eclipse Project
Component: Core (show other bugs)
Version: 3.7   Edit
Hardware: PC Windows XP
: P3 normal (vote)
Target Milestone: 3.7.1   Edit
Assignee: Srikanth Sankaran CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2011-06-25 13:36 EDT by rene CLA
Modified: 2011-08-26 14:54 EDT (History)
4 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
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.