wildcard generic type

A wildcard generic type is an unknown generic type represented with a question mark (?).
* The wildcard is never used as a type argument for a generic method invocation, a generic class instance creation, or a supertype.

Type of bound | Syntax | Example
----- | ----- | -----
Unbounded wildcard | ? | List\<?> l =new ArrayList\<String>();
Wildcard with an upper bound | ? extends type | List\<? extends Number> list = new ArrayList\<Integer>();
Wildcard with a lower bound | ? super type | List\<? super Integer> l =new ArrayList\<Integer>();

<b>Hierarchy of generic List</b>
* List\<Integer> is NOT a List\<Number>
* List\<Integer> is a List\<? extends Integer> and a List\<? super Integer>
* List\<Number> is a List\<? extends Number> and a List\<? super Number>
* List\<? extends Integer> is a List\<? extends Number>
* List\<? super Integer> is a List\<? super Number>
* List\<? extends Number> is a List\<?>
* List\<? super Number> is a List\<?>

Something interesting happens when we work with upper bounds or unbounded wild-cards. The list becomes logically immutable. Immutable means that the object cannot be modified, The problem stems from the fact that Java doesn’t know what type List<? extends Bird> really is. It could be List<Bird> or List<Sparrow> or some other generic type that hasn’t even been written yet.
Why we need a lower bound? With a lower bound, we are telling Java that the list will be a list of String objects or a list of some objects that are a superclass of String. Either way, it is safe to add a String to that list.
Code | Method compiles | Can pass a List\<String> | Can pass a List\<Object>
----- | ----- | ----- | ----- 
public static void addSound(List\<?> list) {list.add("quack");} | No (unbounded generics are immutable) | Yes | Yes 
public static void addSound(List\<? extends Object> list) {list.add("quack");} | No (upper-bounded generics are immutable) | Yes | Yes
public static void addSound(List\<Object> list) {list.add("quack");} | Yes | No (List\<String> is not a List\<Object>. With generics, must pass exact match) | Yes
public static void addSound(List\<? super String> list) {list.add("quack");} | Yes | Yes | Yes