2016-07-05 14 views
4

Ich habe diesen Code, die, wenn sie als Java 7 (Eclipse-Compiler) kompiliert fein kompiliert, aber nicht, wenn ich die Projekteinstellungen auf Java 8 gesetzt:Wildcard in Generika verhalten sich unterschiedlich in Java 7 und 8

package scratch; 

class Param<T extends Comparable<T>> { 
    public Comparable<?> get() { 
    return null; 
    } 
} 

public class Condition<T extends Comparable<T>> { 
    public static <T extends Comparable<T>> Condition<T> isInRange(T lower, T upper) { 
    return null; 
    } 

    public void foo() { 
    Comparable bound = null;     // Line 15 
    Param<?> param = new Param<Double>(); 
    Condition.isInRange(param.get(), bound); // Line 17 
    } 
} 

In Java 7, bekomme ich diese Warnungen:

  • Zeile 15: Vergleichbar ist ein roher Typ. Typ Sicherheit: Verweise auf generische Art Vergleichbare sollten
  • Linie 17 parametriert werden Ungeprüfter Aufruf isInRange (Comparable, vergleichbar) der generischen Methode isInRange (T, T) vom Typ Zustand

Wenn ich <?> in Zeile hinzufügen 15, wird die Warnung gegangen, aber ich dann einen Fehler in Zeile 17 erhalten:

Bound Mismatch: die generische Methode isInRange (T, T) vom Typ Zustand ist nicht anwendbar für die Argumente (Comparable, vergleichbar). Der abgeleitete Typ Vergleichbar ist kein gültiger Ersatz für die beschränkte Parameter>

Weiß jemand, was genau diese Inkompatibilität verursacht?

PS: ich diese hässlichen Abgüsse hinzugefügt, um den Code zu kompilieren unter beiden Versionen von Java zu machen:

Condition.isInRange((Comparable)param.get(), (Comparable) bound); 
+2

Der Eclipse-Compiler hat einige Bugs in Bezug auf Generics, also sollten Sie mit 'javac' testen. – Kayaman

+3

Das hat nichts mit dem Platzhalter zu tun, sondern mit dem * rohen Typ * der 'gebundenen' Variablen. In Java-7 werden dadurch alle Prüfungen zum Methodenaufruf 'isInRange' ausgeschaltet. In Java-8 erkennt die Zieltypisierung immer noch die Ungültigkeit des verschachtelten Aufrufs, ähnlich wie in diesem Szenario (http://stackoverflow.com/a/26285613/2711488). Ich verstehe nicht, warum du denkst, dass dein Typ, der zum rohen 'Komparator' umgewandelt wird, hässlicher ist als die anfängliche Verwendung des Rohtyps. Natürlich ist die zweite Art der Besetzung unsinnig, da 'gebunden 'bereits ein rohes' Vergleichbares 'ist. – Holger

+2

@Kayaman: In diesem Fall ist Eclipse perfekt im Einklang mit 'javac'. – Holger

Antwort

0

Erstens, ich bin kein Experte für Generika so meine Antwort falsch sein könnte. Ich glaube, das Problem ist die Art und Weise, wie die Methode isInRange definiert wird.

<T extends Comparable<T>> 

Dies ist eine rekursive Definition, die an sich kein Problem darstellt. Schauen Sie sich Klassen wie Double, 10 an. Ich glaube, dass aufgrund der Art und Weise, wie rekursive Definition aufgelöst wird, die Typen der Methode (isInRange) eine Klasse sein müssen, die Comparable implementiert, die sich selbst als das generische für Comparable verwendet; z. B.

Verwandte Themen