Generics methods
I found an information in an eBook that:
"If a generic method definition uses the generic type name more than once or uses it outside the formal parameter list of the method, then the generic type cannot be replaced with a wildcard type."
Could anybody explain it using an example ?
Thanks,
Adrian
# 1
The type parameter here
public static <T> void clearList(List<T> list) {
if(list != null)
list.clear();
}
can be replaced by a wildcard:
public static void clearList(List<?> list) {
if(list != null)
list.clear();
}
whereas the type parameter here must be kept:
public static <T> List<T> clearList(List<T> list) {
if(list != null)
list.clear();
return list;
}
# 2
Hi,
I was rather expecting something like:
static <T extends Number> void doSomething(List<T> l, T element) {}
I didn't event think of a return type as that second use of the generic type.
But even then, the author seams to be not clear on what he says.
Let's take the example above. Since element is of type T, it is not only
the case of using the generic type for the second time, but first of all,
this is indication that we are using it inside the method's body (which
the author also adds as the second case).
If the method was:
static <T extends Number> void doSomething(List<T> l1, List<T> l2) {}
then even that we are using that generic type twice, you can rewrite it
using wildcards...
To summarize - if you use generic type as a type of a parameter or a return type,
then you can't use wildcards. And if the generic type is used as a type for a generic
class, then you can change using wildcards. Am I right here ?
Thanks,
Adrian
# 3
> If the method was:
>
> >
> static <T extends Number> void doSomething(List<T>
> l1, List<T> l2) {}
>
>
>
> then even that we are using that generic type twice,
> you can rewrite it
> using wildcards...
No, you can't.
At least not without changing its implied semantics. The method you're showing expects two Lists with the same element type. If you rewrote the method using wildcards, this restriction that binds the two arguments together would get lost. See:
static void doSomething(List<? extends Number> l1, List<? extends Number l2) {}
Now you could call it like this:
doSomething(new ArrayList<Integer>(), new ArrayList<Double>());
This is a usage that the original version didn't allow.
# 4
Ohhh, you are so right !Now I understand what the author got in his mind :)I will be visiting this particular forum quite often, as I still have lots of other questions regarding java's generic without answer ;)Thanks a lot !Adrian
# 5
But the author assertion is false,by example:<T> List<T> emptyList();is not equivalent toList<?> emptyList();R閙i
# 6
Hi,Could you tell something more about it ?My first thought was I can't add anything to the List, which is returned using List<?> emptyList(); Is there anything else I should be aware of ?Thanks,Adrian
# 7
Adrian,
That's the main difference. You can't add anything except null to a List<?>, but with type inference for a specific T in List<T>, you know exactly what you can add. I find the whole type inference thing quite powerful. I've seen a few statements around comparing it to wildcards and they often understate the differences. This seems to be one of those examples!
Alex
# 8
Hi,
You seem to understand the underlying basis of type inference quite well
so perhaps you could try to answer my question in this topic:
http://forum.java.sun.com/thread.jspa?threadID=5172272
and maybe you could point me to the right place where I could
read something sensible about type inference ?
Thanks a lot !
Adrian.