2016-03-03 3 views
3

je travaillais avec TreeSet et trouvé un ClassCastException tout en appelant la méthode TreeSet#add().Pourquoi TreeSet a déclaré TreeSet <E> au lieu de TreeSet <E étend Comparable <E>>

code:

public class Testing { 
    public static void main(String[] args) { 
     TreeSet<Testing> ts = new TreeSet<>(); 
     ts.add(new Testing()); 
    } 
} 

Sortie:

Exception in thread "main" java.lang.ClassCastException: Testing cannot be cast to java.lang.Comparable 
    at java.util.TreeMap.compare(TreeMap.java:1290) 
    at java.util.TreeMap.put(TreeMap.java:538) 
    at java.util.TreeSet.add(TreeSet.java:255) 
    at Testing.main(Testing.java:13) 

Il est clair que c'est parce que TreeSet est une collection ordonnée et il a besoin de les commander Comparable objets, alors pourquoi ne pas déclarer son tapez

public class TreeSet<E extends Comparable<E>> 

et de faire la vérification au cours de la compilation au lieu de jeter exception au moment de l'exécution?

Répondre

7

A TreeSet « élément de ne pas mettre en œuvre Comparable, puisque vous pouvez passer un Comparator à l'un des TreeSet » s constructeurs afin d'imposer un ordre pour les éléments qui ne mettent pas en œuvre Comparable (ou pour les éléments qui font implémentez Comparable lorsque vous souhaitez utiliser une commande autre que l'ordre naturel défini par Comparable).

+2

Je suppose que j'ai demandé trop vite sans passer par l'ensemble du document API ... Merci ... :) – Codebender

0

De la façon dont il est mis en œuvre, vous pouvez commander des articles qui ne peuvent pas décider par eux-mêmes s'ils doivent être commandés dans un endroit plus haut ou plus bas que l'article «autre». Prenez un exemple concret: Vous avez un concours de beauté. Si vous demandez à l'une des filles si elle est plus belle que celle à côté d'elle, elle dira oui. Vous ne pouvez pas les mettre dans un ordre juste en leur demandant. Vous avez donc besoin que quelqu'un d'autre soit responsable de la commande, le comparateur.

Ceci vous permet de commander des articles qui n'ont pas la possibilité de se comparer à un autre article.

1

Comme cela a été mentionné dans d'autres réponses, les clés TreeSet ne peuvent pas être Comparable si le code Comparator personnalisé est spécifié. Il serait toujours possible d'appliquer la vérification à la compilation pour votre cas. Supposons que nous faisons le constructeur par défaut méthode privée et de fournir une usine statique à la place:

public class TreeSet<E> { 
    private TreeSet() {...} 

    public static <E extend Comparable<? super E>> TreeSet<E> newSet() { 
     return new TreeSet<>(); 
    } 
} 

De cette façon, vous serez obligé d'utiliser TreeSet.newSet() et le type de compilation vérification échouerait si vous attribuez à TreeSet<Testing> et Testing ne comparable. Pourquoi cela n'a pas été fait? Parce que les génériques sont apparus dans Java 1.5 seulement, tandis que TreeSet est apparu dans Java 1.2, ce n'était pas un problème ces temps-ci. Maintenant, nous devons faire face à la rétrocompatibilité.