tutorials.de Buch-Aktion 05/2012
Like Tree2Danke
  • 1 Beitrag von Thomas Darimont
  • 1 Beitrag von Thomas Darimont
ERLEDIGT
NEIN
ANTWORTEN
9
ZUGRIFFE
1429
EMPFEHLEN
  • An Twitter übertragen
  • An Facebook übertragen
AUF DIESES THEMA
ANTWORTEN
  1. #1
    Steve222 Steve222 ist offline Mitglied Bronze
    Registriert seit
    Mar 2007
    Ort
    Rheinland
    Beiträge
    46
    Hallo!

    Hoffentlich ist diese Frage genau hier "erlaubt".
    Da es um Datenstrukturen geht, denke ich, ist es wohl korrekt.

    Gegeben sind zwei Listen:

    Code java:
    1
    2
    3
    4
    5
    6
    7
    8
    
             List<Number> list14 = null;
             List<? super Integer> list15 = null;  
     
             //list14 = list15; //  Compilerfehler incompatible types   //Zeile 3
     
             list15 = list14;  //  Zeile 4,  OK
           
             // <? super Integer> bedeutet:  <Integer> und alle Super-Klassen von <Integer>

    Kann mir jemand erklären, warum die Zuweisung in Zeile 4 in Ordnung ist?
    Im konkreten Fall könnte da eine Typ-Zuweisung "<Integer> = <Number>" sein,
    was, denke ich, nicht passt.

    Kann man es so deuten, dass der Compiler großzügig bzw. wohlwollend entscheidet,
    weil bei Zuweisung "<? super Integer> = <Number>" könnte auch
    Typ-Zuweisung "<Number> = <Number>" sein oder auch
    Typ-Zuweisung "<Object> = <Number>"
    sein, was ja passt.

    Viele Grüße

    Steve222
     

  2. #2
    Registriert seit
    Jun 2002
    Ort
    Saarbrücken (Saarland)
    Beiträge
    9.885
    Blog-Einträge
    29
    Hallo,

    schau mal hier:
    http://www.angelikalanger.com/Generi...ts.html#FAQ101
    http://www.tutorials.de/java/367497-...-generics.html

    Schau mal hier:
    Code java:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    
    package de.tutorials;
     
    import java.util.Arrays;
    import java.util.Iterator;
    import java.util.List;
     
    public class SuperGenericsExample {
        public static void main(String[] args) {
            List<Number> numbers = Arrays.<Number>asList(0.0); //Double
            List<? super Integer> superOfIntegers = numbers;
            
            Number number = numbers.get(0); //returns number
            Iterator<Number> numberIterator = numbers.iterator();
            
            Object value = superOfIntegers.get(0); //returns Object NOT Integer ...
            superOfIntegers.set(0, /* accepts only integers*/ Integer.valueOf(1));
            Iterator<? super Integer> superIntegerIterator = superOfIntegers.iterator();
            superOfIntegers.add(/* accepts only integers*/ Integer.valueOf(0));
            
        }
    }
    Die Deklaration von List<? super Integer> superOfIntegers; besagt, dass superOfIntegers zwar Werte vom Typ Integer oder seiner Basis-Klassen enthalten kann, jedoch hier das "Constraint" ? super Integer unterschiedliche Auswirkungen. Zum einen ist superOfIntegers.set(...) fest auf Integer getyped.... man kann also diese Liste nur um tatsächliche Integers erweitern bzw. mit Integern manipulieren...
    Auslesen kann man jedoch nur den "lower bound" ... und der ist in unserem Fall durch das ? -> Object.
    Deshalb gibt die get Methode nur Object zurück.

    Dieser Mechanismus macht sich das PECS-Prinzip zu nutze siehe in den oberen Links für weitere Einzelheiten.


    Gruß Tom
    Steve222 bedankt sich. 
    Java rocks!
    How to become a good Java Programmer?
    Does IT in Java and .Net
    The only valid measurement of code quality: WTFs / minute
    Blog
    Xing
    Twitter

  3. #3
    Steve222 Steve222 ist offline Mitglied Bronze
    Registriert seit
    Mar 2007
    Ort
    Rheinland
    Beiträge
    46
    Hallo Tom,

    Du schriebst u.a.:
    Auslesen kann man jedoch nur den "lower bound" ... und der ist in unserem Fall durch das ? -> Object.
    und das irritiert mich.

    ? super SubType " (wildcard with lower bound), bedeutet
    alle SuperTypen von SubType und SubType selbst.
    Laut Fr.A.Langer ist <? super Integer> eine "wildcard with lower bound" und der lower bound
    ist dann enstprechend "Integer". Oder?

    Es kommt mir vor, als würdest Du unter "lower bound" den SuperTyp verstehen!?

    Viele Grüße
    Steve222
     

  4. #4
    Registriert seit
    Jun 2002
    Ort
    Saarbrücken (Saarland)
    Beiträge
    9.885
    Blog-Einträge
    29
    Hallo,

    okay, kann sein, dass ich da was durcheinander gebracht habe. Finde die Formulierungen ziemlich kompliziert... für mich war der lower Bound der Typ den ich mindestens bekomme beim auslesen...
    Was ist denn genau der upper bzw. lower bound einer generischen Collection? Ist der lower bound der allgemeinste Typ mit dem ich mit der Collection arbeiten kann? Was bedeutet arbeiten in diesem Fall? Lesen? Schreiben? Beides? Weil ...
    List<? super Integer> superOfIntegers -> schreiben kann ich nur Integer ... lesen kann ich jedoch Object (da ja alle möglichen SuperTypen von Integer)zurück kommen können...

    Im Prinzip definiert man ja mit List<? super T> eine Einschränkung für die Verwendung der Liste.
    Diese Einschränkung besagt, dass zur Liste nur Werte vom Typ T hinzgefügt (add(...) ) und nur Werte vom Typ T gesetzt (set(int,...) werden können. Ausgelesen werden können jedoch Werte vom beliebigen Super-Typen von T und da bleibt nur Object über...

    Deshalb ist die Zuweisung im Falle von:
    Code java:
    1
    2
    
    List<Number> numbers = Arrays.<Number>asList(0.0); //Double
    List<? super Integer> superOfIntegers = numbers;

    auch erlaubt... denn ausgelesen werden kann aus superOfIntegers nur Werte vom Typ Object und dass sind Numbers oder Integer auf jeden Fall.

    Aber wie heißts noch so schön: "Wer meint generics zu verstehen hat generics nicht verstanden...."

    Gruß Tom
     
    Java rocks!
    How to become a good Java Programmer?
    Does IT in Java and .Net
    The only valid measurement of code quality: WTFs / minute
    Blog
    Xing
    Twitter

  5. #5
    Steve222 Steve222 ist offline Mitglied Bronze
    Registriert seit
    Mar 2007
    Ort
    Rheinland
    Beiträge
    46
    Hallo Tom,

    gut, dass Du pragmatisch daran gehst und Lesen und Schreiben ausprobierst, aber dennoch sollten die Begrifflichkeiten geklärt werden.

    Du fragtest
    Was ist denn genau der upper bzw. lower bound einer generischen Collection? Ist der lower bound der allgemeinste Typ mit dem ich mit der Collection arbeiten kann?
    Diese Begriffe sind die, die Frau Langer verwendet und ich verstehe sie so:
    1.) lower bound ( ca.: untere Begrenzung) und auch upper bound ( ca.: obere Begrenzung)
    gibt es so erstmal NUR im Zusammenhang mit dem wildcard-Zeichen "?", wenn es um
    Typisierungen von Collections, also dem Thema "generics" geht.
    Wie Du mitteilst geht es darum jeweils Collection-Objekte auf auf einen bestimmten
    Typ, oder auf einige wenige Typen festzulegen.

    Ohne wildcard, also z.B. <String>, bedeutet, dass in dem so markierten Collectionobjekt nur
    Strings hinzugefügt werden dürfen.
    Mit wildcard, also z.B. <? extends String> bedeutet, dass in das so markierte Collectionobjekt nur
    Strings UND Subclass-Objekte von String hinzugefügt werden dürfen. "String" ist dann "upper bound".

    Mit wildcard, also z.B. <? super String> bedeutet, dass in das so markierte Collectionobjekt nur
    Strings UND Superclass-Objekte von String hinzugefügt werden dürfen. "String" ist dann "lower bound".

    Was bedeutet arbeiten in diesem Fall? Lesen? Schreiben?
    Um das Lesen mit get() habe ich mich bisher kaum gekümmert, aber eben habe ich in der
    API nachgeschaut und kann nicht bestätigen, dass get() Object zurückgibt
    Da steht bei List "E get(int index)" wobei E als Typparameter der List erklärt wird und
    der wäre meines Erachtens eben das was innerhalb < > steht.

    List<? super Integer> superOfIntegers -> schreiben kann ich nur Integer ... lesen kann ich jedoch Object (da ja alle möglichen SuperTypen von Integer)zurück kommen können...
    Ja, so wie ich es verstanden alle möglichen SuperTypen von Integer also auch Object.

    Nun ja, mein anfängliches Problem ist noch nicht gelöst.
    Ich bin über die Seite von Nikos P.

    //http://nikojava.wordpress.com/2008/1...jp-generics-25
    zu der anfänglichen Frage gestoßen.

    List<Number> list10 = null;
    List<Integer> list11 = null;
    list11 = list10; // Compiler-Fehler incompatible types
    list10 = list11; // Compiler-Fehler incompatible types ==> ES GILT OFFENBAR KEINE IS-A BEZIEHUNG !

    Wegen dem vorgenanten schließe ich, dass IS-A Relation bei generics keine Rolle spielt.
    Ich denke, dass
    Code java:
    1
    2
    3
    
    List<Number> list14 = null;
             List<? super Integer> list15 = null; 
             list15 = list14;  //  Zeile 4,  OK
    OK ist, ist weil eine der drei Möglichkeiten genau passt, da die IS-A Relation offenbar bei generics keine Rolle spielt. Das meine ich auch mit
    Compiler großzügig bzw. wohlwollend entscheidet
    Aber bei
    Code java:
    1
    2
    3
    
     Queue<? extends Number> q1 = null;
     Queue<? super Integer> q2 = null;
    q1 = q2  //  Compiler-Fehler:  incompatible types
    gäbe es auch mindestens eine Kombination die OK ist, aber es gibt hier auch den Compiler-Fehler "incompatible types..." womit die Theorie "großzügige Entscheidung" ( soll heissen: wenn wenigstens eins passt, dann kein Compiler-Fehler )
    auch nicht stimmen kann!
    Deshalb bin ich erstmal immer noch ratlos.


    Viele Grüße
    Steve222
     

  6. #6
    wakoz wakoz ist offline Mitglied Gold
    Registriert seit
    Apr 2010
    Beiträge
    114
    @steve222
    Verstehe ich das richtig? <? super Integer> darf super typen aufnehmen.

    und du willst eine Collection vom Typ Number in diese Collection vom Typ <? super Integer> schreiben.

    Number ist doch super typ von Integer. Oder verstehe ich hier gerade alles falsch?
     

  7. #7
    Registriert seit
    Jun 2002
    Ort
    Saarbrücken (Saarland)
    Beiträge
    9.885
    Blog-Einträge
    29
    Hallo,

    gut, dass Du pragmatisch daran gehst und Lesen und Schreiben ausprobierst, aber dennoch sollten die Begrifflichkeiten geklärt werden.
    da hast du natürlich recht.

    Wie Du mitteilst geht es darum jeweils Collection-Objekte auf auf einen bestimmten
    Typ, oder auf einige wenige Typen festzulegen.
    Genau.

    Um das Lesen mit get() habe ich mich bisher kaum gekümmert...
    Das sollte man aber nicht außen vor lassen, denn Collections werden IMHO deutlich öfter gelesen als geschrieben.

    ... aber eben habe ich in der
    API nachgeschaut und kann nicht bestätigen, dass get() Object zurückgibt
    Da steht bei List "E get(int index)" wobei E als Typparameter der List erklärt wird und
    der wäre meines Erachtens eben das was innerhalb < > steht.
    Ja genau und was ist dieses E in dem Szenario?
    Richtig: ? super Integer und welchen Typ haben wir dann? -> (? super Integer) und das wäre dann
    allgemein: Object. Etwas anderes kannst du dann nämlich nicht definieren. Das gäbe dann einen
    Compilefehler.
    Code java:
    1
    2
    
    List<? super Integer> superOfIntegers = ...
    Object value = superOfIntegers.get(0);

    Hier liegt wie schon beschrieben ein wichtiger Unterschied:
    Code java:
    1
    2
    3
    
    List<? super Integer> list = null;
    list.add(new Integer(0)); //list.add(E e) -> hier wird nur Integer akzeptiert
    Object integer = list.get(0); //E list.get(int) -> hier wird nur Object garantiert!

    Java Generics sind nicht Covariant... sprich eine List<Integer> ist keine List<Number>, noch nichtmal eine List<Object>
    Siehe auch:
    http://www.fh-wedel.de/~si/seminare/...s/genjava3.htm

    Code java:
    1
    2
    
    List<Integer> ints = null;
    List<Object> os = ints; //Compiler error

    Mit Wildcards kann man diesen Umstand etwas auflösen.
    Code java:
    1
    2
    
    List<Integer> ints = null;
    List<? extends Object> os = ints; //ok

    Code java:
    1
    2
    3
    
    Queue<? extends Number> q1 = null;
    Queue<? super Integer> q2 = null;
    q1 = q2  //  Compiler Fehler

    Hier mal noch zwei Beispiele zu deinem Queue-Fall:
    Code java:
    1
    2
    3
    4
    
    Queue<? extends Number> q1 = null; //q1 garantiert numbers -> Number peek(), akzeptiert: ****? 
    Queue<? super Integer> q2 = null; //q2 garantiert objects -> Object peer(), akzeptiert: Integer
    q1 = q2  //  geht nicht: etwas was Objects garantiert kann nicht plötzlich Numbers garantiert... deshalb Compilerfehler
    q2 = q1; // geht auch nicht

    Was gehen würde:
    Code java:
    1
    2
    3
    4
    
    Queue<Number> q1 = null; //q1 garantiert numbers -> Number peek(), akzeptiert: Number void add(Number)
    Queue<? super Integer> q2 = null; //q2 garantiert objects -> Object peer(), akzeptiert: Integer
    //q1 = q2  //  geht nicht: etwas was Objects garantiert kann nicht plötzlich Numbers garantiert... deshalb Compilerfehler
    q2 = q1; // geht

    Gruß Tom
     
    Java rocks!
    How to become a good Java Programmer?
    Does IT in Java and .Net
    The only valid measurement of code quality: WTFs / minute
    Blog
    Xing
    Twitter

  8. #8
    wakoz wakoz ist offline Mitglied Gold
    Registriert seit
    Apr 2010
    Beiträge
    114
    Eine Liste wie list<? super Integer> nimmt Integer, Number und Object auf. Warum? Weil Object super Klasse von Number und Number super Klasse von Integer ist. Und <? super Integer> besagt das die Liste Integer und dessen super Klassen aufnimmt.
    Und solange rechts etwas steht was nur einem Kriterium erfüllt funktioniert die Zuweisung.

    Während list<Integer> besagt das nur Vollwertige Integer aufgenommen werden.

    Was bedeutet in unserem Fall Vollwertig? Vollwertig bedeutet das das der Typ der aufgenommen wird exakt mit den Vorgaben Übereinstimmen muss. Integer IS-A Number, aber Number IS-Not A Integer. und weil Number kein Integer ist kann eine Zuweisung von list<integer> = list<Number> nicht funktionieren.

    Ich versuche es mal zu verdeutlichen

    die Prüfung des Compilers bei <? super Integer> ist ob die liste die gegeben wird einem der super Typen entspricht
    also Number || Integer || Object, solange nur eins true ergibt wird die gegebene Liste Akzeptiert.

    die Prüfung bei list<Integer> verlangt nach Integer und Prüft nur das ab und solange es false ergibt wird nichts angenommen.
     

  9. #9
    Steve222 Steve222 ist offline Mitglied Bronze
    Registriert seit
    Mar 2007
    Ort
    Rheinland
    Beiträge
    46
    Hallo Tom,

    Du schriebst:
    Ja genau und was ist dieses E in dem Szenario?
    Richtig: ? super Integer und welchen Typ haben wir dann? -> (? super Integer) und das wäre dann
    allgemein: Object. Etwas anderes kannst du dann nämlich nicht definieren. Das gäbe dann einen
    Compilefehler.
    [ Auch wenn ich wohl weniger weiss bzgl. Java als Du... ]

    genau die Stelle:
    ...das wäre dann allgemein: Object...
    Und genau das habe ich bisher anders aufgefasst:
    <? super Integer> steht, denke ich, für Integer oder Number oder Object.
    Also "Integer" ist hier lower bound und somit sind Integer und sene Superklassen
    als Typ erlaubt.


    Im Moment hilft mir das alles zu meiner anfänglichen Frage nicht wirklich weiter, denn es sind einige
    Wiederholungen und auch Fakten, die mir bereits seit längerem belkannt sind.

    wie z.B.
    Java Generics sind nicht Covariant... sprich eine List<Integer> ist keine List<Number>, noch nichtmal eine

    List<Object> Ich schrieb, dass IS-A Relationen bei generics keine Rolle spielen.

    Was mir hoffentlich was nutzt, ist die Anregung zum rumpropieren mit Lesen und Schreiben.
    Aber da bin ich im Moment auf etliches gestoßen was ich einfach nicht einordnen kann
    wie z.B.
    Code java:
    1
    2
    3
    
      Queue<? extends Number> q1 = null;
             boolean boo1 = q1.offer(new Integer(88));  // C-FM capture ..  
             boolean boo2 = q1.add(new Integer(99));   // : cannot find symbol

    Für mich bedeutet Queue<? extends Number> q1 = null; dass in q1
    Integer-Objekte hinzugefügt werden können, weil ...Integer extends Number..
    Integer IS-A Number
    upper bound ist hier Number aber Number-Objekte gehen nicht, weil es die garnicht, weil abstract,
    gibt.

    Das was Du am Ende schreibst ist prinzipiell das gleiche (jetzt nur mit queue anstatt List) was ich ganz am Anfang geschrieben habe, oder nicht? Ich weiß nicht genau wie Du Dich selbst einschätzt bezüglich generics Es gibt da divergente Hinweise...Sofern Du bei generics Lücken hast kannst Du diese aufgrund Deiner Erfahrung bestimmt recht bald schließen.

    Ich habe vor IMMER zu verstehen, warum ein Compilerfehler auftritt.
    Es nur in den meisten Fällen zu wissen, reicht mir nicht.

    Die "wildcards with an upper bzw. lower bound" geben mir gerade in der praktischen
    Verwendung (Lesen, Schreiben) im Moment noch mehr Rätsel auf.

    Viele Grüße
    Steve222
     

  10. #10
    Registriert seit
    Jun 2002
    Ort
    Saarbrücken (Saarland)
    Beiträge
    9.885
    Blog-Einträge
    29
    Hallo,

    ich denke das du hier deine Antwort findest:
    http://www.torsten-horn.de/techdocs/java-generics.htm

    Gruß Tom
    Steve222 bedankt sich. 
    Java rocks!
    How to become a good Java Programmer?
    Does IT in Java and .Net
    The only valid measurement of code quality: WTFs / minute
    Blog
    Xing
    Twitter

Ähnliche Themen

  1. Generics:Typverträglichkeit bei <? super Integer>
    Von Steve222 im Forum Java Grundlagen
    Antworten: 4
    Letzter Beitrag: 20.02.11, 03:42
  2. Generics Syntax
    Von Lastlord im Forum Java
    Antworten: 5
    Letzter Beitrag: 03.11.10, 08:50
  3. Generics
    Von bRainLaG im Forum Java
    Antworten: 3
    Letzter Beitrag: 09.12.09, 12:42
  4. Generics
    Von Conkerchen im Forum Algorithmen & Datenstrukturen mit Java
    Antworten: 1
    Letzter Beitrag: 31.05.09, 19:18
  5. Casten von Generics
    Von dr-oetker im Forum Java
    Antworten: 2
    Letzter Beitrag: 13.04.07, 09:37