Re: generics:< ? >vs.< T >
Robert Klemme wrote:
Trying to post through the old Google Groups interface to see whether
thread disruption occurs here as well.
I'll post this through GG also, but I have no clue what's new or old.
It's the same rule why we do doX(List l) instead of doX(ArrayList l),
i.e. we use the most general type that is sufficient to do what the
method is supposed to do. Similarly we use doX(List<? extends Foo> l)
instead of doX(List<Foo> l) so the method can be applied to a wider
range of arguments.
I see your point. You're right.
The trouble is that generalizing type assertions weakens them. <? ext=
ends
Foo> is a much weaker assertion than <Foo>,
That's exactly the purpose of using bounds, generalization. It shares
this purpose with another construct: interfaces.
...
And that is why you're right.
public void foo( Bar <? extends Baz> bar, Qux <? extends Bax> qux=
);
Is this a typo? Did you mean "Qux <? extends Baz>"?
Yes, and yes.
allows you only very limited conclusions about the type relationships b=
etween
the base types of the two arguments. You cannot assert them to be pr=
ovably
the same type. Eliminating the wildcard allows the compiler to see t=
he guarantee.
There is another way (assuming typo) which also eliminates the
wildcard - but only from the argument list:
public <X extends Baz> void foo( Bar<X> bar, Qux<X> qux );
This method is more useful than
public void foo( Bar<Baz> bar, Qux<Baz> qux );
because it is applicable to a wider range of arguments without any
logical or implementation change. Of course it depends on the usage
(see above) - if there is read and write access (case 3) then of
course you must stick with the version without wildcards.
You can even leave in a wildcard and allow different types with a
relationship
public static <X extends Baz> void foo2(Bar<X> bar, Qux<? extends X>
qux) {
qux.getMember().baz();
bar.setMember(qux.getMember());
}
assuming parametrized "member" in all classes and a method with the
lowercase class name.
Okay, all that is just brilliant.
The rule of thumb is: "Generics should assert the type relationships ne=
eded
for the code to work."
... and they should be as general as possible.
.... and convincing.
....
I do hope that people learn and not mindlessly copy. Unfortunately
there seems to be a significant portion of people around who believe
the do not need to think themselves if they can copy "ready made" code
from somewhere. I even saw people mindlessly copying their own code
over and over again instead of refactoring common parts into functions
or methods. Sigh!
+1.
With the proviso that there is also mindful copying over and over, on
occasion.
--
Lew