Do you know Java: PECS


Do you remember the rule of PECS? If not, read the post quickly!

PECS stands for Produce-Extend, Consume-Super. What does that mean? Let us see an example with types from the standard.

Object

void add(List<Object> list) {
    list.add("string");
    list.add(1);
}

Passing the followings are:

add(new ArrayList<Object>()); // not type safe
add(new ArrayList<String>()); // compile time error

The first is not type safe, the second one does not compile, since ArrayList<String> is not the subtype of List<Object>.

Wildcard

Wildcard ? brings the following.

void add(List<?> list) {
    list.add("string"); // compile time error
    list.add(1);  // compile time error
}

Though, add accepts both ArrayList<String> and ArrayList<Integer>, but not known what kind of parameter is passed during runtime, so adding new elements to the list (writing the list) is not allowed.

Super (Lower bounded wildcard)

void add(List<? super Number> list) {
    list.add(1);
    for (Object number : list) {
        System.out.println(number);
    }
}
  1. ? super T accepts all types between T and Object on the hierarchy chain.
  2. list is writable, all values are accepted where instanceof Number returns true.
  3. list is considered non-readable, except the read value is Object because of type erasure.
  4. We say that with super, new item is consumed by the list.
add(new ArrayList<String>()); // compile time error
add(new ArrayList<Integer>()); // compile time error
add(new ArrayList<>());
add(new ArrayList<Object>());

Extends (Upper bounded wildcard)

void add(List<? extends Number> list) {
    list.add(1); // compile time error
    for (Object number : list) {
        System.out.println(number);
    }
}
  1. ? extends T accepts all types that extends Number, like Float, Double, Integer, and Number.
  2. list is not writale, since Object is the only type which is known in runtime.
  3. list is readable, and the type of the return value can be anything between Number and Object.
  4. We say that with extends, new item is produced from the list.
add(new ArrayList<String>()); 
add(new ArrayList<Integer>()); // compile time error
add(new ArrayList<>());
add(new ArrayList<Object>()); // compile time error

In this post we see how to use generic boundaries and what PECS is.

Code can be found: https://github.com/torokmark/do-you-know-java