Ismael Juma wrote:
Sebastiaan van Erk <[EMAIL PROTECTED]> writes:He also discusses the difference between bounded wildcards and bounded type parameters (one of the problems already encountered).Yes, but he doesn't explain the issue that has left people confused. Bloch says: "These two signatures have identical semantics - boolean addAll(Collection<? extends E> c); - <T extends E> boolean addAll(Collection<T> c);" Once you add a type parameter to E, it either doesn't apply anymore or the compilers are buggy. More specifically, these two are not the same according to the eclipse compiler and javac: - public final <C extends Page<?>> void setResponsePage(final Class<C> cls, PageParameters parameters) - public final void setResponsePage(final Class<? extends Page<?>> cls, PageParameters parameters) The former accepts some class literals that the latter does not.
If two compilers disagree, this would seem to be a bug in at least one of them! :-)
However, I couldn't stand not knowing why the above stuff wasn't working, and I *FINALLY* figured it out and it comes down to this:
In a nutshell:
Foo<Bar<T>> is ****NOT**** a subtype of Foo<Bar<?>>
just like
List<String> is ****NOT**** a subtype of List<Object>
When A is a subtype of B, you can make the assignment B b = (A) a. It is
obvious why you cannot do:
ArrayList<Object> list = new ArrayList<String>();
This is not typesafe, you can do list.add(new Object()) and pollute a
String list with Objects.
Similarly you cannot do:
ArrayList<List<?>> list = new ArrayList<List<String>>(); // bad!!!
Why is that? Because the list instance now has the add(List<?> el)
method!!!!
list.add(new ArrayList<Object>()); // allowed!!!!
Thus you could pollute the List of (List of String) by adding (List of
Object)!!
When you use a type bound, you do not have this problem: 1) public Object method(Foo<? extends Bar<?>> y)You cannot call method((Foo<SubBar<T>>) y) because SubBar<T> is not a subtype of ? extends Bar<?> for the above reasons.
2) public <S extends Bar<?>> Object method(Foo<S> y)The type parameter is bounded, and now it is allowed to use SubBar<T> because the T is captured by the wildcard and the method has signature method(Foo<SubBar<T>> y) and thus takes a type *without* wildcards.
So, it is after all, not a compiler error, and not semantically equivalent. Pretty mind-bending stuff though. :-) Who said generics are easy? ;-)
Regards, Sebastiaan
Regards, Ismael
smime.p7s
Description: S/MIME Cryptographic Signature
