2016-07-20 1 views
2

Cette expression lambda pour comparer 2 objets:java 8 de comparaison des génériques lambda - avertissements du compilateur

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

produit cet avertissement de compilation:

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 

Cette expression lambda pour comparer les 2 T objets:

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

produit cet avertissement de compilation:

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 

Votre résolution avec des explications/commentaires très apprécié

Répondre

2

Vous ne pouvez pas définir un Comparator qui peut se comparer Comparable arbitraires s que vous ne pouvez pas comparer un String à un Integer, en dépit de la mise en œuvre à la fois Comparable. Vous avez besoin d'une variable de type pour formuler la contrainte que les deux arguments de la méthode Comparator.compare doivent être compatibles pour une comparaison.

Mais il est impossible de définir un tel Comparator générique en utilisant un champ, car vous ne pouvez pas introduire de paramètres de type lors de la déclaration d'un champ. Il fonctionne uniquement en utilisant une méthode de fabrication:

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

ou

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

que vous pouvez utiliser comme

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); 

qui montre que la donnée JRE, il produit une instance singleton, étant à égalité avec un comparateur stocké dans un domaine en termes de performance. Mais du point de vue des génériques, ils ont des types incompatibles, ce qui rend impossible de définir une seule variable contenant ce comparateur et étant compatible avec Integer et String en même temps.

L'impossibilité de déclarer un champ avec des paramètres de type est la raison pour laquelle Collections.EMPTY_LIST mais j'ai complété avec Collections.emptyList() quand Génériques ont été introduites ou pourquoi la nouvelle méthode Comparator.naturalOrder(), adressant le même but que votre tentative, est une méthode plutôt qu'un champ.

+0

Merci, Holger. C'est logique et bien expliqué (un programmeur pour le président). – Felix