Generics
Prev: classes-and-interfaces Next: enums-and-annotations
26. Don’t Use Raw Types
// Don't, this loses type safety
private final Collection stamps = ...;
// parameterized, good
private final Collection<Stamp> stamps = ...;
You can also use unbounded wildcard types, which can hold any item. However, this still allows you to put in a null (since all Ts are nullable)
static int numElementsInCommon(Set<?> s1, Set<?> s2) {}
For class literals or instanceof
, you have to use the raw type.
27. Eliminate Unchecked Warnings
This (I think this should be fine tbh)
Set<Lark> exaltation = new HashSet();
Has a warning
warning: [unchecked] unchecked conversion
Set<Lark> exaltation = new HashSet();
^
required: Set<Lark>
found: HashSet
You need to use the diamond operator:
Set<Lark> exaltation = new HashSet<>();
Try to avoid warnings, and if there are any warnings still existing, suppress it with a @SuppressWarnings("unchecked")
annotation, and a comment why it is permissible:
@SuppressWarnings("unchecked")
// casting from HashSet to Set is ok
Set<Lark> exaltation = new HashSet();
28. Prefer Lists to Arrays
Arrays are covariant, which means any subtype can fit in at compile time:
Object[] objectArray = new Long[1];
objectArray[0] = "what" // Throws ArrayStoreException
For a list, this won’t compile:
List<Object> ol = new ArrayList<Long>();
ol.add("what"); // doesn't compile
29. Favor Generic Types
I agree, use generics if possible for parameterized types. Not much to say
30. Favor Generic Methods
Also agree, not much to say:
Turn this:
public static Set union(Set s1, Set s2) {
Set result = new HashSet(s1);
result.addAll(s2);
return result;
}
Into:
public static <E> Set<E> union(Set<E> s1, Set<E> s2) {
Set<E> result = new HashSet<>(s1);
result.addAll(s2);
return result;
}
You can use recursive type bounds as well, which come in handy:
public static <E extends Comparable<E>> E max(Collection<E> c);
31. Use Bounded Wildcards to Increase API Flexibility
Assume you have this method for a stack to push all items. This only allows you to push the type E, not subtypes of E.
// pushAll method without wildcard type - deficient!
public void pushAll(Iterable<E> src) {
for (E e : src) { push(e); }
}
You would like to be able to add items that are also subtypes:
public void pushAll(Iterable<? extends E> src) {
for (E e : src) { push(e); }
}
Same with pop:
public void popAll(Iterable<E> dst) {
while(!isEmpty()) { dst.add(pop()); }
}
Instead, you want to be able to pop supertypes, so you would use wildcards for that:
public void popAll(Collection<? super E> dst) {
while (!isEmpty())
dst.add(pop());
}
32: Combine Generics and Varargs Judiciously
Prev: classes-and-interfaces Next: enums-and-annotations