When is it recommended to do:
public <E> boolean hasPropertyX(List<E extends User> alist);
versus
public boolean hasPropertyX(List<? extends User> alist);
It would appear they both work just as well.
When is it recommended to do:
public <E> boolean hasPropertyX(List<E extends User> alist);
versus
public boolean hasPropertyX(List<? extends User> alist);
It would appear they both work just as well.
Without typed return value, the only difference I can think of is explicit typing of the first way of declaration during method call.
So for example you are using it inside typed class C<K extends String>
List<V extends String> input = ...;
boolean var = obj.hasProperty<K>(input);
will raise the compiler error. But why would any one want to do so...
Nice question even if most likely the answer is both are the same.
Explicitly naming the generic type as E
and not ?
has these uses (as far as I can think of):
0) To tie the return type to some part of the argument type - for example:
public <E> E getSomeElement(List<E> lst) { ... }
// ^ If we don't name the argument type as having E,
// then we can't specify the return type as being E
1) To tie some part of the argument type to some part of the enclosing type:
class Storage<E> {
E item;
public void replace(Storage<E> st) { item = st.item; }
// ^ This wouldn't work if we wrote Storage<?> instead
}
2) To tie some combination of the argument types, return type, and enclosing type (see #0 and #1).
We can get away with the anonymous type name ?
if we don't care about the actual type. Here is a basic example:
boolean allEqual(List<?> lst, Object y) {
for (Object x : lst) { // Any reference can be stored as Object
if (!y.equals(x)) // equals takes an Object
return false;
}
return true;
}
// ^ We could also rewrite this example with List<E> and "E x".
Another example:
int intSum(List<? extends Number> lst) {
int sum = 0;
for (Number x : lst) // We only care that the list element is a Number
sum += x.intValue();
return sum;
}
// ^ We could also rewrite with List<E extends Number> and "E x".
Alternate reading: http://docs.oracle.com/javase/tutorial/extra/generics/wildcards.html
I suppose in that particular example they both do work effectively the same way in terms of type checking. However, if you extend the generic type to require a base or superclass of some class it can be useful. e.g.
public <E extends User> boolean hasPropertyX(List<E> alist);
This at least enforces that you're receiving some subclass of User
.
EDIT
You can use a wildcard to achieve the same thing:
public boolean hasPropertyX(List<? extends User> alist);
But this won't work if, for example, you want to use the generic for multiple parameters:
public <E extends Automobile> void crashAutos(List<E> list1, List<E> list2);
This enforces the generic type on both arguments, whereas the following code does not force the two lists to contain the same type:
public void crashAutos(List<? extends Automobile> list1, List<? extends Automobile> list2);
I could call that method with two different subclasses of the Automobile
class:
List<Car> cars = ...
List<Truck> trucks = ...
crashAutos(cars, trucks);
Whereas using generics enforces the same type for both arguments.
Differences between generics and wildcard unknown types:
The related question:
Use ? extends
when you only need to retrieve from the List:
User getElement(List<? extends User> list, int i) {
return list.get(i);
}
Use ? super
when you only need to add to the List:
void addElement(List<? super User> list, User u) {
list.add(u);
}
Use E extends
when you both need to retrieve and add:
<E extends User> void swapElements(List<E> list, int i, int j) {
E temp = list.get(i);
list.set(i, list.get(j));
list.set(j, temp);
}
? extends User
: We don't know the exact type of the List, but we can retrieve a User
from it.? super User
: We don't know the exact type of the List, but we can put a User
in it.E extends User
: We don't necessarily know the exact type of the List but it conforms to constraints such that:
E
.E
is at least User
.E
from the List and put E
in the List.See also: