web-dev-qa-db-fra.com

Pourquoi .compareTo () dans une interface alors que .equals () est dans une classe en Java?

Je veux savoir pourquoi la .compareTo() est dans l'interface Comparable alors qu'une méthode comme .equals Est dans Object classe. Pour moi, il semble arbitraire pourquoi une méthode comme .compareTo() n'est pas déjà dans la classe Object.

Pour utiliser .compareTo(), vous implémentez l'interface Comparable et implémentez la méthode .compareTo() selon vos besoins. Pour la méthode .equals(), vous remplacez simplement la méthode dans votre classe, car toutes les classes héritent de la classe Object.

Ma question est pourquoi une méthode comme .compareTo() dans une interface que vous implémentez plutôt que dans une classe comme Object? De même, pourquoi la méthode .equals() dans la classe Object et pas dans une interface doit-elle être implémentée?

30
Wesley

Tous les objets ne peuvent pas être comparés, mais tous les objets peuvent être vérifiés pour leur égalité. Si rien d'autre, on peut voir si deux objets existent au même endroit en mémoire (égalité de référence).

Qu'est-ce que cela signifie pour compareTo() sur deux Thread objets? Comment un fil est-il "plus grand que" un autre? Comment comparez-vous deux ArrayList<T>s?

Le contrat Object s'applique à toutes Java classes. Si une seule classe ne peut pas être comparée à d'autres instances de sa propre classe, alors Object ne peut pas exiger qu'elle fasse partie de l'interface.

Joshua Bloch utilise les mots clés "ordre naturel" pour expliquer pourquoi une classe pourrait vouloir implémenter Comparable. Toutes les classes n'ont pas un ordre naturel comme je l'ai mentionné dans mes exemples ci-dessus, donc toutes les classes ne doivent pas implémenter Comparable ni Object avoir la méthode compareTo.

... la méthode compareTo n'est pas déclarée dans Object. ... Elle a un caractère similaire à la méthode Object de equals, sauf qu'elle permet des comparaisons d'ordre en plus des comparaisons d'égalité simples, et elle est générique. En implémentant Comparable, une classe indique que ses instances ont un ordre naturel .

Efficace Java, deuxième édition : Joshua Bloch. Point 12, page 62. Les points de suspension suppriment les références à d'autres chapitres et exemples de code.

Pour les cas où vous voulez imposer un ordre à une classe non -Comparable qui n'a pas d'ordre naturel, vous pouvez toujours fournissez une instance Comparator pour faciliter le tri.

58
user22815

JLS §4.3.2 définit l'objet class de la manière suivante:

4.3.2. L'objet de classe

La classe Object est une superclasse (§8.1.4) de toutes les autres classes.

Tous les types de classe et de tableau héritent (§8.4.8) des méthodes de classe Object, qui se résument comme suit:

  • La méthode clone est utilisée pour créer un doublon d'un objet.

  • La méthode equals définit une notion d'égalité d'objet, qui est basée sur une comparaison de valeur et non de référence.

  • La méthode finalize est exécutée juste avant la destruction d'un objet (§12.6).

  • La méthode getClass renvoie l'objet Class qui représente la classe de l'objet.

  • Un objet Class existe pour chaque type de référence. Il peut être utilisé, par exemple, pour découvrir le nom complet d'une classe, ses membres, sa superclasse immédiate et toutes les interfaces qu'elle implémente.

    Le type d'une expression d'appel de méthode de getClass est Class<? extends |T|>T est la classe ou l'interface recherchée (§15.12.1) pour getClass.

    Une méthode de classe déclarée synchronized (§8.4.3.6) se synchronise sur le moniteur associé à l'objet Class de la classe.

  • La méthode hashCode est très utile, avec la méthode equals, dans des tables de hachage telles que Java.util.Hashmap.

  • Les méthodes wait, notify et notifyAll sont utilisées dans la programmation simultanée à l'aide de threads (§17.2).

  • La méthode toString renvoie une représentation String de l'objet.

C'est pourquoi equals est dans Object mais compareTo est dans une interface distincte. Je suppose qu'ils voulaient garder Object aussi minimal que possible. Ils ont probablement pensé que presque tout Objects aurait besoin de equals et hashCode (ce qui est vraiment juste une forme de test d'égalité) mais tous les objets n'auraient pas besoin d'avoir un concept d'ordre , qui est utilisé pour compareTo.

8
durron597

En plus de l'excellente réponse de Snowman, rappelez-vous que Comparable est depuis longtemps une interface générique. Un type n'implémente pas compareTo(object), il implémente compareTo(T)T est son propre type. Cela ne peut pas être implémenté sur object, car object ne connaît pas la classe qui en sera dérivée.

object aurait pu définir une méthode compareTo(object), mais cela aurait permis non seulement ce que Snowman souligne, une comparaison entre deux ArrayList<T>s ou entre deux Threads, mais même une comparaison entre un ArrayList<T> et un Thread. C'est encore plus absurde.

2
hvd

Supposons que j'ai deux références d'objet: X identifie une instance de String contenant le contenu "George"; Y identifie l'instance de Point contenant les coordonnées [12,34]. Considérez les deux questions suivantes:

  • X et Y identifient-ils des objets équivalents?

  • Est-ce que X doit trier avant, après ou équivalent à Y?

Le fait que X et Y identifient des instances de types non liés ne pose aucun problème lors de l'examen de la première question. Les objets ne peuvent être considérés comme équivalents que si leurs types partagent une base commune qui les définit comme équivalents; puisque String et Point n'ont pas une telle base (leur seul type de base commun considère tous les objets distincts comme non équivalents) la réponse est simplement "non".

Le fait que les types ne soient pas liés, cependant, pose un énorme problème en ce qui concerne la deuxième question. Certains types définissent des relations de classement entre leurs instances, et certaines relations de classement peuvent même s'étendre sur plusieurs types [par exemple il serait possible pour BigInteger et BigDecimal de définir des méthodes de comparaison qui permettraient de classer les instances de chaque type par rapport aux instances de l'autre], mais il n'est généralement pas possible d'en prendre deux des instances arbitraires et demandez "Doit X trier avant, après ou équivalent à Y" et dériver un ordre total. Il serait possible de demander "Doit X trier avant, après, équivalent ou non classé par rapport à Y" si les objets devaient déclarer un ordre cohérent mais pas total un, mais la plupart des algorithmes de tri nécessitent des commandes totales. Ainsi, même si tous les objets pouvaient implémenter une méthode compareTo si "non classé" était un retour valide, une telle méthode ne serait pas suffisamment utile pour justifier son existence.

0
supercat