2015-06-24 6 views
6

Ich kämpfte darum, einen richtigen Titel für diese Frage zu finden, weil das Phänomen, das ich beobachtete, sehr seltsam ist. Daher überspringe ich es, mein Problem wörtlich zu erklären und zeige stattdessen (hoffentlich) selbst beschreibenden Code. Betrachten Sie die folgende parametrisierte Klasse:Warum verliert der Eclipse-Compiler den festen Typparameter?

public class GenericOptional<T> { 

    public GenericOptional(T someValue) {} 

    public T getValue() { return null; } 

    public Optional<String> getOptionalString() { return Optional.empty(); } 
} 

Was Ich mag zu betonen ist, dass der Rückgabetyp Optional<String> des Verfahrens getOptionalString() nicht davon abhängt, den Typ-ParameterT.

haben nun einen Blick auf die folgenden Code, der innerhalb Eclipse-Luna 4.4.2 mit 8u45 Java kompiliert wird:

public static void main(String[] args) { 
    Object obj = new GenericOptional<>(Boolean.TRUE); 
    GenericOptional go = (GenericOptional) obj; 
    Optional os = go.getOptionalString(); 
} 

Die lokale Variable os hat den Typ Optional ohne Typ- ParameterString! Der Eclipse Compiler hat die Information über den festen Typ-Parameter verloren. Weiß jemand warum?

Betrachten Sie nun ein zweites Codebeispiel:

public static void main(String[] args) { 
    Object obj = new GenericOptional<>(Boolean.TRUE); 
    GenericOptional<?> go = (GenericOptional) obj; 
    Optional<String> os = go.getOptionalString(); 
} 

die lokale Variable go als GenericOptional<?> den Rückgabetyp der Methode getOptionalString() jetzt Optional<String> Durch die Deklaration ist wie erwartet.

Kann jemand dieses Verhalten erklären?

Antwort

4

Sie das Verhalten von raw types gegenüber. Wenn Sie einen unformatierten Typ verwenden, werden Generics vollständig deaktiviert, unabhängig davon, ob eine Verbindung zwischen der generischen Signatur des Members und dem Typparameter der Klasse besteht.

Der Grund dafür ist, dass Rohtypen sind eine Funktion für die Rückwärtskompatibilität nur mit Pre-Generics-Code. Entweder haben Sie Generika oder Sie nicht.

Wenn die generische Methode auf dem tatsächlichen Typparameter der Klasse hängt nicht, das Problem zu beheben einfach:

GenericOptional<?> go = (GenericOptional<?>) obj; 
Optional<String> os = go.getOptionalString(); 

<?> Verwendung impliziert „Ich weiß nicht, die tatsächlichen Typen Parameter und I don Es ist mir egal, aber ich benutze Generic type checking ".

+0

Vielen Dank für die Antwort. Kocko gab die gleiche Antwort und ich weiß nicht, wie ich Ihnen die richtige/beste Zustimmung geben soll. Aufgrund der Tatsache, dass Sie die Frage zuerst beantwortet haben, obwohl Sie keinen Beispielcode zur Unterstützung Ihrer Erklärung angegeben haben, werde ich Ihnen die "hilfreichste" Genehmigung geben. Wenn Sie denken, dass Kockos Antwort für Leute, die wissen wollen, wie es funktioniert, von größerem Wert ist, lassen Sie mich Nein und ich werde die "äußerst hilfreiche" Zustimmung an Kocko weiterleiten. – Harmlezz

4

Es geht nicht um Eclipse oder so, sondern um rohe Typen.

Lassen Sie sich diese Schnipsel Bewertung:

public static void main(String[] args) { 
    Object obj = new GenericOptional<>(Boolean.TRUE); 
    GenericOptional go = (GenericOptional) obj; 
    Optional os = go.getOptionalString(); 
} 

Hier bist du eine rohen Instanz GenericOptional, zu schaffen, das bedeutet, dass die Typ-Parameter-Information wird vollständig ausgeschaltet werden. Also, Instanziieren ein rohGenericOptional bedeutet, dass die Instanz, die Methoden wie folgt aussetzen:

public class GenericOptional { 

    public GenericOptional(Object someValue) {} 

    public Object getValue() { return null; } 

    public Optional getOptionalString() { return Optional.empty(); } 
} 

Wenn wir aber nun die zweite Schnipsel überprüfen

public static void main(String[] args) { 
    Object obj = new GenericOptional<>(Boolean.TRUE); 
    GenericOptional<?> go = (GenericOptional) obj; 
    Optional<String> os = go.getOptionalString(); 
} 

können wir sehen, dass Sie machen eine generische Instanz von GenericOptional. Auch es ist-Typ Parameter ist <?>, wird der Compiler nicht Ausschaltzeiten Sorge um Typ-Parameter, so wird belichten die Instanz die getOptionalString() Methode parametriert, wie folgt aus:

public Optional<String> getOptionalString() { return Optional.empty(); } 
+0

Vielen Dank Kocko für die nette Erklärung. Bitte beachten Sie den Kommentar, den ich zu Holgers Antwort hinzugefügt habe, warum ich ihm die "hilfreichste" Genehmigung gegeben habe. Ich hoffe, es geht Ihnen gut mit dieser Entscheidung. – Harmlezz

Verwandte Themen