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