Community
Participate
Working Groups
//suspicious compiler errors on mix of for each and generics class Node{} interface Set1<N extends Node> extends Iterable<N>{} interface Set2 extends Iterable<Node>{} class SetIterator<N extends Node> implements Iterator<N>{ public N next(){return null;} public boolean hasNext(){return true;} public void remove(){} } interface Set3<N extends Node> extends Iterable<N>{ SetIterator<N> iterator(); } class X{ void f1(Set1 s){ Node n_ = s.iterator().next(); // ^Type mismatch: cannot convert from Object to Node // this was unexpected (s can only contain types derivered from Node) for (Node n : s){ // ^Type mismatch: cannot convert from Object to Node // this was unexpected } } void f2(Set2 s){ Node n_ = s.iterator().next(); for (Node n : s){ } } void f3(Set3 s){ Node n_ = s.iterator().next(); // (^ no error here) for (Node n : s){ // ^Type mismatch: cannot convert from Object to Node // this is even stranger as we already know that s.iterator().next() have the right type } } }
It indeed looks surprising, now javac agrees with us.
Got it, problem comes from the fact Set1 is a raw type, where Set2 isn't. When Set1 (raw) is used, its supertype is also erased. Thus the supertype of raw Set1 is raw Iterable as opposed to Iterable<N>; hence it is inheriting #iterator() which returns an instance of raw Iterator. Instead of using Set1, use Set1<Node> instead. Added GenericTypeTest#test809
also read http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=5006039