Re: generics:< ? >vs.< T >
On Wednesday, March 9, 2011 1:32:17 PM UTC+1, Lew wrote:
Generics are tricky because we tend to think of them as instructions. Th=
ey
are not.
'<?>' does not mean "any type"; it means "an arbitrary but unknown subtyp=
e of
Object". '<T>' doesn't mean "any type"; it means "a particular inferrabl=
e
(therefore known) type". The biggest difference is that the wildcard doe=
s not
assert which particular type is in play, but the type parameter does.
That's why they're incompatible. No way the compiler can assert that som=
e
unknown wildcard type (the capture of the wildcard's bound) is reliably=
compatible with the assertrf type 'T'. We just don't know which type the=
wildcard represents and cannot match it to 'T'.
You also see that from error messages where wildcard captures are numbered =
so each position of <? extends Foo> gets its own calculated type and of cou=
rse it is *not* true that for each A extends Foo and B extends Foo: A can b=
e assigned from B or B can be assigned from A.
I had to puzzle out a related issue a few days back. I had a method with t=
his signature
public static <V2, V1 extends V2> void copy1(final Map<?, V1> source,
final Map<? super String, V2> target) {
// work
}
Then, for convenience reasons I wanted parameter "target" to be returned in=
order to be able to do Map<...> m = copy(..., new HashMap<...>, ...) in =
one line.
First solution was
public static <V2, V1 extends V2> Map<? super String, V2> copy2(final Map=
<?, V1> source,
final Map<? super String, V2> target) {
// work
return target;
}
This compiles but when used in a line like this
final Map<String, MapsTest> m2 = copy2(source, new HashMap<String, MapsTe=
st>());
compiler errors out with
Type mismatch: cannot convert from Map<capture#2-of ? super String,MapsTest=
to Map<String,MapsTest>
The solution was to mention the type of "target" and return value explicitl=
y:
public static <V2, V1 extends V2, M extends Map<? super String, V2>> M co=
py3(
final Map<?, V1> source, final M target) {
// work
return target;
}
Now the compiler knows that both are of the same type and assignment doesn'=
t error out.
Btw, has anybody an explanation why I can do copy1() from above but not
public static <V1, V2 super V1> void copy0(final Map<?, V1> source,
final Map<? super String, V2> target) {
// work
}
? This errors out with a syntax error at "super" between "V2" and "V1".
Cheers
robert