2016-05-22 12 views
2

Ich habe eine Eigenschaft auf einer Klasse, die von einem Typ ist List<List<Value>>, und ich versuche es mit einer Klasse zu instanziiert, die ein Subtyp dieser Schnittstellen und Klassen ist, etwa so:Wie verschachtelte Generika richtig implementiert werden?

public List<List<Value>> rows = new DbRowList<MyRow>(); 

Wo DbRowList ist eine Art, die ArrayList erstreckt:

public class DbRowList<E extends List<Value>> extends ArrayList<E> implements List<E> { 

    public boolean add(E element) { 
     MyRow row = new MyRow(); 
     return super.add(row); // Compile-time error 
    } 
} 

und MyRow ist:

public class MyRow extends ArrayList<Value> implements List<Value> { 
    public Table table; 
} 

Und doch wird dies nicht wegen der Fehler in der return-Anweisung von DbRowList.add() kompilieren:

The method add(E) in the type ArrayList<E> is not applicable for the arguments (MyRow) 

Warum ist es nicht anwendbar? MyRow erstreckt sich ArrayList<Value>, die selbst eine List ist.

Antwort

0

Ihre Fehlermeldung ist selbsterklärend: Der Compiler erwartet, dass ein Argument vom Typ E an super.add() übergeben wird. Ihr Code ist überschreiben die add() Methode, und so muss folgen, indem Sie das Objekt des Typs E übergeben. So sollte der Code wie folgt aussehen:

public boolean add(E element) { 
    return super.add(E); // no error here 
} 

Wenn Sie sich fragen, wie Sie Ihre Klasse verwenden, erstellen Sie einfach die MyRow Objekt außerhalb und geben es in:

List<List<Value>> rows = new DbRowList<MyRow>(); 
MyRow row = new MyRow(); 
rows.add(row); 
0

allererst Sie dies nicht tun brauche diese alle "implements List<E>", denn ArrayList selbst implementiert List.

In Bezug auf Ihre Kompilierung-Fehler, so ist es falsch, Nutzung und Verständnis von Generika. Sie können bestimmte Instanz bestimmten Klasse hinzuzufügen, wenn Sie diese Art Variable zum Beispiel von DbRowList Klasse angeben wird, so dass dieses Stück Code kompiliert und Arbeit:

public boolean add(E element) { 
    return super.add(element); 
} 

public static void main(String[] args) { 
    new DbRowList<MyRow>().add(new MyRow()); 
} 

Aber wenn Sie möchten Ihr Beispiel zwingen kompilieren Sie können immer auf generische Art machen Casting E, weil Generika nichts im laufenden Betrieb sind, und Listen Instanzen von irgendwelchen Typen enthalten:

public boolean add(E element) { 
    MyRow row = new MyRow(); 
    return super.add((E) row); 
} 
0

Warum versuchen Sie, dies zu tun?

Sie überschreiben die Methode zum Hinzufügen einer leeren ArrayList anstelle des tatsächlichen Argumentwerts. Element wird nicht weitergegeben.

Und der Grund ist einfach: Sie versuchen, es an Super zu übergeben.hinzufügen, die

E 

will, aber sie passieren

ArrayList<E>. 

Was Sie tun sollten, ist einfach nicht die Methode überschreiben, aber richtig definieren Klasse:

public class DbRowList<E extends List<Value>> extends ArrayList<E>{ 

} 

void testMethod(){ 
    List<List<Value>> rows = new DbRowList<>(); 
    rows.add(new ArrayList<>()); 
} 

edit: tatsächlich, während des Tippens ich verstanden dass es nicht genau das ist, was du willst, also bitte klar: Müssen Sie Zeilen speichern oder Elemente in bestimmten Zeilen speichern? Was ich beschrieben habe, ist zum Speichern ganzer Zeilen, aber was du vielleicht brauchst, ist eine Karte, die auf Zeilen zeigt. Sie könnten dann Elemente zu den angegebenen Zeilen hinzufügen, ohne eine neue Zeile oder eine Zeile zum Laden/Suchen zu erstellen, die Sie benötigen.

Verwandte Themen