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);
}
}