2016-11-02 17 views
3

EDIT: Ja, das kann ein Duplikat sein. Aber während die andere Frage verwandt ist mit "Was ist eine Kettensäge und wie benutze ich sie?" meins ist eher wie "Ich versuche hier ein Loch mit dieser Maschine zu bohren und es funktioniert nicht - was ist los?". Natürlich lautet die Antwort: "Benutze keine Kettensäge!" und leicht gefunden, sobald Sie wissen, dass Sie mit einer Kettensäge beschäftigen.Java Generics: "Nested" -Typ Parameter?

Aber ich wusste nicht einmal, dass meine Frage zu "rohen Typen vs. wilden Karten" verwandt war und deshalb diese Frage nicht gefunden hat - also ist diese Frage vielleicht noch nützlich für andere wie mich.

ORIGINAL FRAGE: Lassen Sie uns sagen, dass ich die folgende Datenstruktur, die einen Eintrag in meiner Benutzeroberfläche darstellt:

public static abstract class RowItem<T> { 

    public final T value; 

    public RowItem(T value) { 
     this.value = value; 
    } 
} 

Nun würde Ich mag folgendes tun:

public static abstract class EpgRowItem<T> extends RowItem<Pair<String, T>> { 

    public EpgRowItem(Pair<String, T> value) { 
     super(value); 
    } 
} 

public static final class EpgRowProgramItem extends EpgRowItem<Program> { 

    public EpgRowProgramItem(Pair<String, Program> value) { 
     super(value); 
    } 
} 

public static final class EpgRowOtherDateItem extends EpgRowItem<LocalDate> { 

    public EpgRowOtherDateItem(Pair<String, LocalDate> value) { 
     super(value); 
    } 
} 

Also, in Worten: Ein EpgRowItem ist ein RowItem, der ein Pair enthält, von dem das erste Mitglied immer ein String ist und das zweite Mitglied alles sein kann. Ferner ist ein EpgRowProgramItem ein EpgRowItem, in dem das zweite Glied des Paares ein Program ist. In ähnlicher Weise ist ein EpgRowOtherDateItem ein EpgRowItem, in dem das zweite Mitglied des Paares ein LocalDate ist.

scheint dies funktioniert, bis ich in meinem Code an einem anderen Ort haben:

List<OverlayPresenter.EpgRowItem> programs = ...; 
OverlayPresenter.EpgRowItem epgRowItem = programs.get(0); 
String channelId = epgRowItem.value.first; // DOESN'T COMPILE?! 

ich der Compiler wissen fühlen sollte, dass epgRowItem.value IMMER ein Pair<String, ?> sein müssen und folglich epgRowItem.value.first muss immer ein String sein.

Eigentlich scheint es nicht einmal den ersten Teil zu kennen, ich. e. hat die folgenden nicht kompilieren entweder:

Pair<String, ?> pair = epgRowItem.value; // epgRowItem.value is an Object?! 

Was mache ich falsch? Frage ich nur zu viel von Generika von Java?

+0

Ja, jetzt, dass ich die Antwort weiß, es i s natürlich ein Duplikat. Aber da ich "umgekehrt" gefragt habe - angefangen mit einem konkreten Problem, nicht mit einem Schlüsselwort auf hoher Ebene - denke ich, dass es immer noch eine gültige Frage ist und für andere von Nutzen sein kann. –

Antwort

4

Sie in Schwierigkeiten geraten, weil Sie den rohen Typen verwenden EpgRowItem (a raw Typ ist ein parametrisierte Typ für die Sie keine Typparameter angeben, diese existieren, weil die Rückwärtskompatibilität mit Java 1.4 und älter):

List<OverlayPresenter.EpgRowItem> programs = ...; 
OverlayPresenter.EpgRowItem epgRowItem = programs.get(0); 

See: What is a raw type and why shouldn't we use it?

einen Typ-Parameter verwenden, oder zumindest ein Platzhalter:

List<OverlayPresenter.EpgRowItem<?>> programs = ...; 
OverlayPresenter.EpgRowItem<?> epgRowItem = programs.get(0); 
String channelId = epgRowItem.value.first; // OK 
+0

Oh, das ist interessant. Bis jetzt fühlte ich mich immer ziemlich sicher mit Java Generics, aber das war neu für mich. Vielen Dank! –