2015-06-08 12 views
6

Im Zusammenhang mit that Frage.Warum können wir keine Platzhalter für die Methode mit zwei Parametern erfassen?

Ich weiß über Wildcard-Capturing. Zum Beispiel werden die folgenden könnten zum Umkehren einer Liste verwendet:

public static void reverse(List<?> list) { rev(list); } //capturing the wildcard 
private static <T> void rev(List<T> list) { 
    List<T> tmp = new ArrayList<T>(list); 
    for (int i = 0; i < list.size(); i++) { 
     list.set(i, tmp.get(list.size()-i-1)); 
    } 
} 

Jetzt versuche ich die gleiche Sache für diese Art von Situation zu schreiben:

private int compare (Comparable<?> upper, Comparable<?> lower){ 
    return comp(upper, lower); //The method comp(Comparable<T>, Comparable<T>) is not applicable for the arguments (Comparable<capture#5-of ?>, Comparable<capture#6-of ?>) 
} 

private <T> int comp(Comparable<T> upper, Comparable<T> lower){ 
    return upper.compareTo((T) lower); 
} 

erwartete ich, dass es war in Ordnung zusammengestellt auch. Ist es möglich, Wildacrds für Methoden mit zwei oder mehr Parametern auf diese Weise zu erfassen?

Antwort

2

Bei diesem Verfahren

private <T> int comp(Comparable<T> upper, Comparable<T> lower){ 
    return upper.compareTo((T) lower); 
} 

beiden Parameter gemeinsam nutzen die gleichen Typ-Parameter.

Inzwischen dies für die andere Methode ist nicht wahr:

private int compare (Comparable<?> upper, Comparable<?> lower){ 
    return comp(upper, lower); 
} 

Hier hat der Compiler keine Hinweise darauf, dass die Typ-Parameter für upper und lower gleich sind und das wird sich weigert, warum grünes Licht zu geben, Zusammenstellung.

Wenn beide Methoden dieselben Typparameter verwenden sollen, können Sie den Typparameter class-scoped festlegen. Zum Beispiel:

public class YourClass<T> { 
    private int comp(Comparable<T> upper, Comparable<T> lower){ 
     return upper.compareTo((T) lower); 
    } 

    private int compare (Comparable<T> upper, Comparable<T> lower){ 
     return comp(upper, lower); 
    } 
} 

Eine weitere Option (wenn Sie nicht über die erste mögen) wäre eine einzuführen und die gleiche Obergrenze für die Typ-Parameter für comp() und compare(). Zum Beispiel:

private <T extends SomeSuperClass> int comp(Comparable<T> upper, Comparable<T> lower){ 
    return upper.compareTo((T) lower); 
} 

private <T extends SomeSuperClass> int compare (Comparable<T> upper, Comparable<T> lower){ 
    return comp(upper, lower); 
} 

Außerdem, wenn Sie das Gießen in den comp() Verfahren vermeiden wollen, können Sie dies tun:

public class YourClass<T extends SomeSuperClass & Comparable<T>> { 
    private int comp(T upper, T lower){ 
     return upper.compareTo(lower); 
    } 

    private int compare (T upper, T lower){ 
     return comp(upper, lower); 
    } 
} 
+0

Also können wir einfach den socnt type-Parameter zur Vergleichs-Methode hinzufügen. Aber es wird sehr unsicher aussehen. Welche Art von Problemen werden wir damit wohl bekommen? – user3663882

+0

Ich meine 'private int Comp (vergleichbar oberen, vergleichbar unteren)' – user3663882

+0

Wenn Sie die Typparameter zwischen Methoden teilen möchten, entweder den Typ-Parameter-Klasse-Bereich, oder führen Sie die gleiche obere Grenze für beide Sie. –

4

Da, wie ich in meiner Antwort auf Ihre andere Frage sagte, kann der Compiler nicht wissen, dass die beiden ? für den gleichen Typ stehen.

Die beiden ? stehen jeweils für einen unbekannten Typ. Die compare-Methode benötigt zwei Comparable Objekte für den gleichen Typ T. Wenn Sie compare von der comp-Methode aufrufen, kann der Compiler nicht sicher sein, dass die zwei ? für denselben Typ stehen.

+0

Aber was, wenn wir die Generika mit raws ersetzen? Welche Schwierigkeiten werden wir wahrscheinlich bekommen? – user3663882

+0

Wenn Sie unformatierte Typen verwenden, wird die Kompilierung zwar bestanden, Sie erhalten jedoch eine Warnung, dass zur Laufzeit eine ClassCastException wahrscheinlich auftritt. Und Generics helfen, solche Fehler zu vermeiden. –

+0

Wenn Sie Raw-Typen verwenden, wechselt der Compiler in den Rückwärtskompatibilitätsmodus mit weniger Typprüfung. Aber Sie sollten keine rohen Typen verwenden; siehe: [Was ist ein Rohtyp und warum sollten wir ihn nicht verwenden?] (http://stackoverflow.com/questions/2770321/what-is-a-raw-type-and-why-shouldnt-we-use) -it/2770692) – Jesper