FULL PRODUCT VERSION :
java version "1.5.0"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0-b64)
Java HotSpot(TM) Client VM (build 1.5.0-b64, mixed mode, sharing)
ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows XP [version 5.1.2600]
A DESCRIPTION OF THE PROBLEM :
foreach loop (for :) requires an array or an Iterable objet.
The method iterator() of Iterable has a return type
typed Iterator<T> but this type is too restrictive and could be
relaxed to Iterator<? extends T>.
foreach loop only reads information from the Iterator<T>
so it could use an iterator typed Iterator<? extends T>.
Furthermore, Iterator has no method that takes a
T as argument so Iterator<T> is too restrictive because
it doesn't permit the use of subtypes of T.
Because Iterator<? extends T> is a subtype of
Iterator<T>, the proposed change is straighforward.
Note perhaps the same idea could be applyed to
Collection class.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
compile the code
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
it compile without compiler error
ACTUAL -
the program doesn't compile
ERROR MESSAGES/STACK TRACES THAT OCCUR :
incompatible types
found : java.util.Iterator<capture of ? extends T>
required: java.util.Iterator<T>
return c1.iterator();
Chooser.java line 22 27 octobre 2004 15:34:08
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
public class Chooser<T> implements Iterable<T> {
public Chooser(Collection<? extends T> c1,
Collection<? extends T> c2) {
this.c1=c1;
this.c2=c2;
}
public Iterator<T> iterator() {
if (c1.size()<c2.size())
return c1.iterator();
else
return c2.iterator();
}
private final Collection<? extends T> c1;
private final Collection<? extends T> c2;
public static void main(String[] args) {
ArrayList<String> l1=new ArrayList<String>();
Collections.addAll(l1,args);
ArrayList<Integer> l2=new ArrayList<Integer>();
l2.add(3);
for(Comparable<?> c:new Chooser<Comparable<?>>(l1,l2))
System.out.println(c);
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
the workaround is funny, create a Iterator<T> that wraps
the Iterator<? extends T>.
public Iterator<T> iterator() {
final Iterator<? extends T> it;
if (c1.size()<c2.size())
it=c1.iterator();
else
it=c2.iterator();
return new Iterator<T>() {
public boolean hasNext() {
return it.hasNext();
}
public T next() {
return it.next();
}
public void remove() {
it.remove();
}
};
}
###@###.### 10/27/04 19:13 GMT