2016-11-20 3 views
0

Ich habe einige Beispielprogramme auf Generics Upper/Lower Grenzen versucht .. Generics Upper Bound gibt Kompilierungsfehler ... Aber Lower Bound ist in Ordnung. Ich versuche gerade, eine Liste des Typs T in eine Menge und versuchen oberen und unteren Grenze Szenarien.Generics Upper Bound Wildcard gibt Kompilierungsfehler

Bitte helfen, das Problem mit testUpperBound (T t) -Methode zu identifizieren und warum genau das testLowerBound (T t) Methode kompilieren und die testUpperBound (T t) man nicht. Ich habe andere ähnliche Themen überprüft. Aber ich habe es immer noch nicht verstanden.

Bitte lassen Sie mich wissen, wenn Sie weitere Informationen benötigen.

public class TestGenerics<T> 
    { 

     public static void main(String...args) 
     { 
      List<String> list = new ArrayList<>(); 
      list.add("New ArrayList"); 
      new TestGenerics<List<String>>().testUpperBound(list); 
      new TestGenerics<List<String>>().testLowerBound(list); 

     } 

     public void testLowerBound(T t) 
     { 
      Set<? super ArrayList<T>> lowerBoundSet = new HashSet<>(); 
      lowerBoundSet = new HashSet<List<T>>(); 
      ArrayList<T> list = new ArrayList<>(); 
      list.add(t); 
      lowerBoundSet.add(list); // compiles.. 

      out.println(lowerBoundSet); 
     } 

     public void testUpperBound(T t) 
     { 
      Set<? extends List<T>> upperBoundSet = new HashSet<>(); 
      upperBoundSet = new HashSet<List<T>>(); 
      ArrayList<T> list = new ArrayList<>(); 
      list.add(t); 
      upperBoundSet.add(list); // Doesn't compile.. 

      out.println(upperBoundSet); 
     } 

    } 

Antwort

0

Hier haben Sie Ihre Antwort:

Explanation of the get-put principle

Es Java-Regel, das ist alles. Ich kann Ihnen ein Beispiel mit Ihrem Code, warum es gefährlich wäre, wenn Kompilation übergeben:

public void extendsExample(){ 
    Set<? extends List<? extends String>> setOfList = new HashSet<>(); 
    Set<ArrayList<String>> setOfArrayList = new HashSet<>(); 

    // now setOfList var refers to a set 
    // which contains a arraylist of String 
    setOfList = setOfArrayList; 

    // compilation fails 
    setOfList.add(new LinkedList<String>()); 
} 

Stellen Sie sich vor der Kompilierung nicht ausfällt.
Es bedeutet setOfArrayList Instanz, die eine Menge ist, die ArrayList Instanzen enthalten sollte, enthält jetzt eine Liste von LinkedList Element.

Wenn Sie auf setOfArrayList iterieren, werden Sie nicht ausschließlich ArrayList<String> Elemente wie erwartet haben. Es ist nicht sicher und deshalb schlägt die Kompilierung fehl.

Hier das Beispiel mit <? super:

public void superExample(){ 
    Set<? super ArrayList<String>> setOfArrayList = new HashSet<>(); 

    // compilation ok 
    setOfArrayList.add(new ArrayList<String>()); 
    // new anonymous type derivating from ArrayList 
    ArrayList<String> derivedArrayList = new ArrayList<String>(){ 
    }; 
    // compilation ok 
    setOfArrayList.add(derivedArrayList); 
} 
+0

Super :) Endlich habe ich es klar .... Danke David ..! . Geschätzt und akzeptiert die Antwort. –

0

Sie können nicht eine Sammlung parametrisierte mit <? extends SomeType> ändern. Java erlaubt das einfach nicht, da es keine sichere Aktion ist. add() ändert die Sammlung, so dass Sie es nicht tun können. Es gibt keine solche Beschränkung ist für <? super SomeType>

+0

Danke für die Antwort Yaroslav ... Aber könnten Sie bitte helfen, herauszufinden, was genau der Unterschied zwischen unteren und oberen Methoden in meinem Code ist, wo niedriger kompiliert und oberen nicht? –

+0

Uh nicht ganz, Sie können nicht _insert_ in eine 'Collection ', aber Sie können in eine 'Collection ' einfügen, und umgekehrt (kann von '' abrufen und kann nicht von einem '' abrufen). Iirc können Sie immer noch von einem '' mit Casting abrufen, aber im Allgemeinen ist es eine Erweiterung von PECS – Rogue

+0

Was den Grund hinter der Einschränkung ... Es bezieht sich auf Typ löschen. Java kennt die genaue Parametrisierung in Laufzeit nicht, daher ist die Modifikation eine potentiell gefährliche Operation für obere beschränkte Sammlungen. Es gibt viele Beispiele dafür, was passieren könnte, wenn es im Internet keine solche Einschränkung gäbe. –

0

Einfach gesagt, wir wissen nicht, zum Zeitpunkt der Kompilierung, welche Art von Listen im upperBoundSet enthalten ist. Es könnte ein Set<ArrayList<T>> sein, oder es könnte ein Set<LinkedList<T>> sein, oder es könnte eine von vielen anderen Alternativen sein.

Wenn es sich herausstellt, ein Set<LinkedList<T>> zu sein, dann ist das Hinzufügen eines ArrayList zu ihm offensichtlich eine schlechte Idee. Aber weil wir nicht wissen, welchen Typ der Inhalt des Sets hat, nimmt es die sicherere Option und blockiert sie.