I am noticing some odd behavior when using bounded wildcards. When I use a bounded wildcard as a method parameter, I see the expected behavior. This code takes a list of RuntimeException
or its subclasses and prints them:
public static void foo(List<? extends RuntimeException> exceptions) {
for (RuntimeException ex : exceptions) {
System.out.println(ex);
}
}
When passing a list of unchecked exceptions, it prints them out without issue.
However, when using a bounded wildcard outside of a method parameter, it seems to apply the opposite of whatever bound is stated (if I write extends
, it is treated as super
and vice versa).
public static void main(String[] args) {
List<? extends RuntimeException> arr = new ArrayList<>();
arr.add(new IllegalArgumentException()); // DOES NOT COMPILE
}
The compiler complains:
java: incompatible types: java.lang.StringIndexOutOfBoundsException cannot be converted to capture#1 of ? extends java.lang.RuntimeException
When I change List<? extends RuntimeException>
to List<? super RuntimeException>
, the code compiles without error when given a subclass of RuntimeException
. This is the opposite of what I expected to happen. Can anyone explain this behavior?
Edit: no objects can be added to a list declared with a bounded wildcard. The second example fails to compile because it is using the add() method. Explained here.