Upper bounds werden dort benutzt, wo ich eine Klasse wo ich eine Klasse referenziere, deren Methode ich (nachher) aufrufe und ich definieren möchte, dass diese Methode keine spezifischeren Parameter-Objekte verlangt, als von mir im Lover-Bound angegeben. Z.B. werde ich nur Früchte liefern, also soll die Methode keine Orangen verlangen.

List<? super Frucht> fruchtListe;

Siehe hierzu Lower Bounds – Wozu?

 

<?>,  <? super …> dürfen nicht in der Typparameter-Sektion einer Generischen Klasse verwendet werden. Folgendes geht nicht:

public class GenerischeKlasse<?> //falsch!

public class GenerischeKlasse<? super Number> //falsch!

 

Der Lower Bound bezeichnet die Restriktion der aktuellen Parametrisierung der Generischen Klasse. Er bezeichnet NICHT die upper Bound des danach dieser Klasse in irgendeiner Methode übergebenen Parameters:

public class UpperBound1 {
    public static void main(String[] args) {
        List<? super Number> list = new ArrayList<Number>();
        //Folgendes geht selbstverständlich, weil: 
        // List<? super Number> sagt aus, dass <T> in 
        // :List.add(T value) mit Number oder etwas unspezifischerem
        // aktuell parametrisiert sein muss sein muss.
        //Es darf also z.B. sein:
        //  List<Object> mit Methode add(Object value)            oder
        //  List<Number> mit Methode add(Number value)
        // Und: add(Object v) und add(Number v) haben keine Problem mit Integer als Parameter
        list.add(Integer.valueOf("89")); 


        //Achtung beim Retrieval von Werten aus "? super" referenzierten Objekten:
        //
        //Integer i = list.get(0);      //Incompatible types:
        Integer i = (Integer) list.get(0); //Riskant!!
        Object o = list.get(0);
    }
}