• Archiv der Kategorie: Generics

Upper Bounds

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

 

Lower Bounds – Wozu?

<? super MyClass>

Wozu sind Lower Bounds nützlich? Weshalb kann es hilfreich sein eine Klasse (als Input-Parameter) zu verlangen, nicht nicht spezifischer parametrisiert ist als vorgegeben?

Antwort: Weil ich für mich als Back-Caller die Anforderung bezüglich Spezifikationsgrad einschränke.

Das heisst: Wenn ich eine Methode eines Callbacks aufrufen muss, dann möchte ich sicherstellen, dass diese Method nichts genaueres verlangt als ich geben kann. Z.B. Ich kann Früchte zurückgeben, aber spezifikas z.B. von Trauben kann ich nicht liefern. Oder ich kann Number zurückgeben, nicht aber Double.

Beispiel:

WllCallYou bieted die multiply(WillBeCalled<? super Number> callback, int i1, int i2) Methode an, um zwei Integer miteinander zu multiplizieren und das Resultat an die getResult(T result) Methode des Callbacks zürück zu geben. Das Resultat wird aber nichts spezifischeres als Number sein. Das heisst: Der Callback darf nicht spezifischer als Number parametrisiert sein: <? super Number>

public class WillCallYou {
    public static void multiply(WillBeCalled<? super Number> callback, int i1, int i2){
        Integer integerResult = i1 * i2;
        callback.getResult(integerResult);
    }
}
public class WillBeCalled<T> {
    public void getResult(T result){
        System.out.println("The result is " + result);
    }
}
public class Main {
    public static void main(String[] args) {
        WillCallYou.multiply(new WillBeCalled<Number>(), 3, 4);
        WillCallYou.multiply(new WillBeCalled<Object>(), 3, 4);

        //Wrong first argument type ...
        //WillCallYou.multiply(new WillBeCalled<Float>(), 3, 4);
    }
}
Schließen