Problem with nested parameter

Here is the snippet:

import java.util.*;

publicclass Test{

publicstaticfinalvoid main(String[] argv){

List<String> ls =new ArrayList<String>();

List<Iterator><String>> li =new ArrayList<Iterator><String>>();

Test.fs(ls);

Test.f0(li);

Test.f1(li);

Test.f2(li);

Test.f3(li);

}

publicstatic <T>void fs(List<?extends T> x){}

publicstaticvoid f0(List<Iterator><String>> x){}

publicstatic <T>void f1(List<Iterator><T>> x){}

publicstatic <T>void f2(List<Iterator><?extends T>> x){}

publicstatic <T>void f3(List<?extends Iterator<?extends T>> x){}

}

Try as I might, I don't understand why the call to f2 fails with

Test.java:11: <T>f2(java.util.List<java.util.Iterator><?extends T>>) in Test

cannot be applied to (java.util.List<java.util.Iterator><java.lang.String>>)

Test.f2(li);

^

fs, f0 and f1 are sanity checks. I have enough "intuition" of generics by now

to have divined that f3 might just work but I am still baffled as towhy it works

since AFAICT an Iterator<? extends T> does not extend Iterator<T>.

This is with Sun javac 1.5 but the Eclipse compiler rejects the call to f2, too.

[2784 byte] By [xolotla] at [2007-11-27 0:29:43]
# 1
http://blogs.sun.com/ahe/entry/why_is_the_capture_of
PeterAhea at 2007-7-11 22:32:20 > top of Java-index,Core,Core APIs...
# 2

Thanks for the reply but I don't see the relevance of your blog entry

to this problem. But first let me submit a different and simpler code

sample since the wildcard upper bounds and in turn the whole

capture business turn out not to be germane to the issue at hand.

import java.util.*;

public class Test {

public static final void main(String[] argv) {

List<String> ls = new ArrayList<String>();

List<Iterator><String>> li = new ArrayList<Iterator><String>>();

Test.f0(ls);

Test.f1(ls);

Test.f2(li);

Test.f3(li);

Test.f4(li);

Test.f5(li);

}

public staticvoid f0(List<?> x) {}

public static <T> void f1(List<T> x) {}

public staticvoid f2(List<Iterator><?>> x) {}

public static <T> void f3(List<Iterator><T>> x) {}

public staticvoid f4(List<? extends Iterator<?>> x) {}

public static <T> void f5(List<? extends Iterator<T>> x) {}

}

Alll the calls compile except the one to f2, which fails with:

Test.java:10: f2(java.util.List<java.util.Iterator><?>>) in Test cannot be

applied to (java.util.List<java.util.Iterator><java.lang.String>>)

Test.f2(li);

^

Notice how there is no mention of any capture in the error message.

At this point there are three things I don't understand:

1) Why does f2 fail but not f3? To me both look equally "universal"

in the context of this short sample.

2) Why does the problem manifest itself only when the parametrized

type is nested, i.e., why does f0 pass but not f2?

3) Lastly, as before I still cannot articulate any reason why f4 is the

desired workaround.

xolotla at 2007-7-11 22:32:20 > top of Java-index,Core,Core APIs...
# 3

One can further simplify your example bv getting rid of functions:

List<Iterator><String>> li = new ArrayList<Iterator><String>>();

List<Iterator><?>> li2 = li:

The assignment to li2 will also not compile.

The expression Iterator<?> denotes not a concrete type but a family of types, a.k.a. all Iterators parameterized by an arbitrary type.

In contrast to this, the expression List<Iterator><?>> denotes a concrete, fully usable type: A List that stores all kinds of Iterators.

Now, if the above assignment were allowed, it would be possible to do this:li2.add(new ArrayList<Integer>().iterator());

Thus, the original list of String-Iterators would be corrupted!

This also explains why your function f4 solves the problem:

the expression List<? extends Iterator<?>> once again denotes a family of types and cannot be abused to corrupt the original List.

HTH

McNeppa at 2007-7-11 22:32:20 > top of Java-index,Core,Core APIs...
# 4

Thanks! This is a significant adjustment to my understanding of generics and it will

take me a little while to process it but I think I can make sense of this new reading.

I was parsing List<Iterator><?>> as a (list-of-iterators) (of any type) and not as you did.

Now if I wanted that semantics, is there any way to get it?

xolotla at 2007-7-11 22:32:20 > top of Java-index,Core,Core APIs...
# 5
I think this is one of the greatest (and last) hurdles you will have to cross. It's all downhill from here! :-)
dannyyatesa at 2007-7-11 22:32:20 > top of Java-index,Core,Core APIs...