Member-only story

Effective Java! Use Bounded Wildcards to Increase API Flexibility

Kyle Carter
7 min readMay 21, 2021

Today we take on a bit of a complicated topic but one that, when done correctly, can really make your code much more flexible in its usage. Previously we have talked about how parameterized types are invariant. This means that for two types, TypeA and TypeB, Collection<TypeA> can not be either a subtype or super type of Collection<TypeB>. Making this more concrete, List<String> is not a subtype of List<Object>. This is because any object can go into List<Object> but not any object can go into List<String>. While this may follow logically, sometimes we want/need more flexibility and that's what the chapter we are reviewing today covers.

Let’s consider a previous example we looked at.

public class Stack<E> {
public Stack();
public void push(E e);
public E pop();
}

Above is the currently exposed API. Let’s say we want to add a new method to add many items to the stack at once. We may consider writing it as such:

public void pushAll(Iterable<E> newItems) {
for (E e : newItems) {
push(e);
}
}

This will compile and work fine but we do lose some flexibility that we may want. Let’s consider an example where this may lead to frustration:

Stack<Number> numberStack = new Stack<>();
Iterable<Integer> integers = ...;
numberStack.pushAll(integers);

While the above feels like it should work (Integer being a subtype of Number) it actually won't…

--

--

Kyle Carter
Kyle Carter

Written by Kyle Carter

I'm a software architect that has a passion for software design and sharing with those around me.

No responses yet