I'm a newbie in Generic and my question is: what difference between two functions:
function 1:
public static <E> void funct1 (List<E> list1) {
}
function 2:
public static void funct2(List<?> list) {
}
The first signature says: list1 is a List of Es.
The second signature says: list is a List of instances of some type, but we don't know the type.
The difference becomes obvious when we try to change the method so it takes a second argument, which should be added to the list inside the method:
import java.util.List;
public class Experiment {
public static <E> void funct1(final List<E> list1, final E something) {
list1.add(something);
}
public static void funct2(final List<?> list, final Object something) {
list.add(something); // does not compile
}
}
The first one works nicely. And you can't change the second argument into anything that will actually compile.
Actually I just found an even nicer demonstration of the difference:
public class Experiment {
public static <E> void funct1(final List<E> list) {
list.add(list.get(0));
}
public static void funct2(final List<?> list) {
list.add(list.get(0)); // !!!!!!!!!!!!!! won't compile !!!!!!!!!
}
}
One might as why do we need <?>
when it only restricts what we can do with it (as @Babu_Reddy_H did in the comments). I see the following benefits of the wildcard version:
The caller has to know less about the object he passes in. For example if I have a Map of Lists: Map<String, List<?>>
I can pass its values to your function without specifying the type of the list elements. So
If I hand out objects parameterized like this I actively limit what people know about these objects and what they can do with it (as long as they stay away from unsafe casting).
These two make sense when I combine them: List<? extends T>
. For example consider a method List<T> merge(List<? extends T>, List<? extends T>)
, which merges the two input lists to a new result list. Sure you could introduce two more type parameters, but why would you want to? It would be over specifying things.
add
method work, while get
doesn't give you anything useful. Of course that triggers the next question: why don't generics have lower bounds?For a more in depth answer see: When to use generic methods and when to use wild-card? and http://www.angelikalanger.com/GenericsFAQ/FAQSections/TypeArguments.html#FAQ203