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.
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.
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
Differences between generics and wildcard unknown types:
The related question:
When to use generic methods and when to use wild-card?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With