🎓 A1Learner
🔍
0 of 40 lessons completed

Java Wildcards

A wildcard is a question mark used as a type argument when the exact element type is unknown or flexible. Wildcards let one method accept lists of related types.

Reading an unknown list

show accepts a list of any element type. It reads the size and the first element as an Object.

import java.util.ArrayList;
import java.util.List;
public class Main {
  static void show(List<?> list) {
    System.out.println(list.size());
    Object first = list.get(0);
    System.out.println(first);
  }

  public static void main(String[] args) {
    ArrayList<String> names = new ArrayList<>();
    names.add("Ana");
    names.add("Ben");
    show(names);
    ArrayList<Integer> scores = new ArrayList<>();
    scores.add(90);
    show(scores);
  }
}

A producer of numbers

total reads each element as a Number and adds its doubleValue. Integer and Double lists both fit the extends bound.

import java.util.ArrayList;
import java.util.List;
public class Main {
  static double total(List<? extends Number> numbers) {
    double sum = 0;
    for (Number n : numbers) {
      sum += n.doubleValue();
    }
    return sum;
  }

  public static void main(String[] args) {
    ArrayList<Integer> scores = new ArrayList<>();
    scores.add(10);
    scores.add(20);
    System.out.println(total(scores));
    ArrayList<Double> prices = new ArrayList<>();
    prices.add(1.5);
    prices.add(2.5);
    System.out.println(total(prices));
  }
}

A producer refuses an add

addScore tries to put an Integer into a List<? extends Number>. The list might really hold Doubles, so the compiler refuses the add.

import java.util.ArrayList;
import java.util.List;
public class Main {
  static void addScore(List<? extends Number> numbers) {
    numbers.add(Integer.valueOf(90));
  }

  public static void main(String[] args) {
    ArrayList<Integer> scores = new ArrayList<>();
    addScore(scores);
    System.out.println(scores.size());
  }
}

A consumer takes integers in

fill adds two integers to any list that can hold them. The list here is a List<Number>, and its contents print afterwards.

import java.util.ArrayList;
import java.util.List;
public class Main {
  static void fill(List<? super Integer> list) {
    list.add(10);
    list.add(20);
  }

  public static void main(String[] args) {
    ArrayList<Number> numbers = new ArrayList<>();
    fill(numbers);
    System.out.println(numbers);
    Object first = numbers.get(0);
    System.out.println(first);
  }
}

Example

import java.util.ArrayList;
import java.util.List;
public class Main {
  static void fill(List<? super Integer> list) {
    list.add(10);
    list.add(20);
  }

  static double total(List<? extends Number> numbers) {
    double sum = 0;
    for (Number n : numbers) {
      sum += n.doubleValue();
    }
    return sum;
  }

  public static void main(String[] args) {
    ArrayList<Number> numbers = new ArrayList<>();
    fill(numbers);
    System.out.println(numbers.size());
    System.out.println(total(numbers));
  }
}

Key points

  • List<?> is a list of an unknown type, and its elements can be read as Object.
  • List<? extends Number> is a producer that gives Number values out, so reads are safe.
  • Nothing can be added to a producer list, because the exact element type stays unknown.
  • List<? super Integer> is a consumer that takes Integer values in.
  • PECS stands for Producer Extends, Consumer Super, and it sums up which bound fits each job.

In this example, the consumer method fills a list of Number with integers, and the producer method then totals the same list. The super bound fits the writing job and the extends bound fits the reading job.

Note

A value read from a consumer list comes back typed as Object.

Try it Yourself

Edit the code, then press Run.

Running is simulated

Exercise

Which declaration fits a method that only reads numbers from a list?