2016-07-20 27 views
2

Dieser Lambda-Ausdruck 2 Objekte vergleichen:Java 8 Lambda Generika Komparator - Compiler-Warnungen

private static final Comparator NATURAL_ORDER_COMPARATOR1 = 
     (Comparator) (final Object o1, final Object o2) -> ((Comparable) o1).compareTo(o2); 

erzeugen diese Kompilierung Warnung:

warning: [unchecked] unchecked call to compareTo(T) as a member of the raw type Comparable 
(Comparator) (final Object o1, final Object o2) -> ((Comparable) o1).compareTo(o2); 
where T is a type-variable: 
T extends Object declared in interface Comparable 

Dieser Lambda-Ausdruck vergleichen 2 T-Objekte:

private final Comparator<T> NATURAL_ORDER_COMPARATOR2 = 
     (Comparator<T>) (final T o1, final T o2) -> ((Comparable<T>) o1).compareTo(o2); 

erzeugt diese Kompilierungswarnung:

warning: [unchecked] unchecked cast 
(Comparator<T>) (final T o1, final T o2) -> ((Comparable<T>) o1).compareTo(o2); 
required: Comparable<T> 
found: T 
where T is a type-variable: 
T extends Object declared in class Tree01 

Ihre Auflösung mit Erklärung/Kommentaren viel

Antwort

2

Sie können keine Comparator definieren, die beliebige Comparable s vergleichen können, wie Sie kein String zu einem Integer trotz beide Implementierung Comparable vergleichen können. Sie benötigen eine Typvariable, um die Einschränkung zu formulieren, dass beide Argumente der Methode Comparator.compare für einen Vergleich kompatibel sein müssen.

Es ist jedoch unmöglich, solch ein generisches Comparator mit einem Feld zu definieren, da Sie beim Deklarieren eines Felds keine Typparameter eingeben können. Es funktioniert nur mit einer Factory-Methode:

public static <T extends Comparable<? super T>> Comparator<T> naturalOrder() { 
    return (a,b) -> a.compareTo(b); 
} 

oder

public static <T extends Comparable<? super T>> Comparator<T> naturalOrder() { 
    return Comparable::compareTo; 
} 

die Sie wie verwenden

Comparator<Integer> ci = naturalOrder(); 
Comparator<String> cs = naturalOrder(); 
// in the current version of Oracle's JRE/OpenJDK this will print true 
System.out.println(ci==(Object)cs); 

die zeigt, dass mit dem angegebenen JRE, eine Singleton-Instanz erzeugt, wobei vergleichbar mit einem Komparator in einem Feld in Bezug auf die Leistung gespeichert. Aber aus generischer Sicht haben sie inkompatible Typen, was es unmöglich macht, eine einzelne Variable zu definieren, die diesen Komparator hält und mit Integer und String gleichzeitig kompatibel ist.

Die Unmöglichkeit, ein Feld mit Typ-Parameter zu erklären, ist der Grund, warum Collections.EMPTY_LIST mit Collections.emptyList() ergänzt wurde, wenn Generika eingeführt wurden oder warum die neue Methode Comparator.naturalOrder(), den gleichen Zweck wie Ihr Versuch, Adressierung, ist eine Methode, eher als ein Feld.

+0

Danke, Holger. Das ist sinnvoll und schön erklärt (ein Programmierer für den Präsidenten). – Felix