Chcę wiedzieć, dlaczego .compareTo()
jest w Comparable
interfejsie, podczas gdy metoda podobna .equals
jest w Object
klasie. Wydaje mi się arbitralne, dlaczego takiej metody .compareTo()
nie ma już w Object
klasie.
Aby użyć .compareTo()
, zaimplementuj Comparable
interfejs i zaimplementuj .compareTo()
metodę do swoich celów. W przypadku .equals()
metody po prostu przesłonisz metodę w swojej klasie, ponieważ wszystkie klasy dziedziczą od Object
klasy.
Moje pytanie brzmi: dlaczego metoda jest taka jak .compareTo()
w interfejsie, który implementujesz, a nie w klasie takiej jak Object
? Podobnie, dlaczego .equals()
metoda Object
ma zostać zaimplementowana w klasie, a nie w jakimś interfejsie?
java
language-design
interfaces
Wesley
źródło
źródło
Eq
klasy).Odpowiedzi:
Nie wszystkie obiekty można porównać, ale wszystkie obiekty można sprawdzić pod kątem równości. Jeśli nic więcej, można sprawdzić, czy dwa obiekty istnieją w tym samym miejscu w pamięci (równość odniesienia).
Co to znaczy
compareTo()
na dwóchThread
obiektach? W jaki sposób jeden wątek jest „większy niż” inny? Jak porównać dwaArrayList<T>
s?Object
Umowa ma zastosowanie do wszystkich klas Java. Jeśli nawet jednej klasy nie można porównać do innych instancji własnej klasy,Object
nie może wymagać, aby była częścią interfejsu.Joshua Bloch używa słów kluczowych „porządek naturalny”, wyjaśniając, dlaczego klasa może chcieć zaimplementować
Comparable
. Nie każda klasa ma naturalne uporządkowanie, jak wspomniałem w moich przykładach powyżej, więc nie każda klasa powinna implementowaćComparable
ani nie powinnaObject
mieć tejcompareTo
metody.Effective Java, Second Edition : Joshua Bloch. Punkt 12, strona 62. Elipsy usuwają odniesienia do innych rozdziałów i przykładów kodu.
W przypadkach, gdzie nie chcą narzucić kolejność na niebędącego
Comparable
klasy, które nie mają naturalną kolejność, zawsze można dostarczyćComparator
instancji to rodzaj pomocy.źródło
==
drugie, ma to pusty pierścień. Pomijając zbędne wartości domyślne, można znaleźć uzasadnione powody, dla których nie należy zakładać, żeequals
wszystkie klasy, ponieważ nie wszystkie typy mogą obsługiwać relację równoważności.==
”, ponieważ sposób tworzenia tych klas jest szczegółem implementacji, ale język uniemożliwia ukrycie. Można powiedzieć, że ktokolwiek porównujący dwaInteger
s przez odniesienie jest idiotą, ale pozwolenie na rozpoczęcie porównania jest jeszcze głupsze.W JLS §4.3.2 definiuje
class
obiekt w następujący sposób:Właśnie dlatego
equals
jest w,Object
alecompareTo
jest w osobnym interfejsie. Spekulowałbym, że chcieli ograniczyćObject
do minimum. Prawdopodobnie doszli do wniosku, że prawie wszyscyObjects
będą potrzebowaćequals
ihashCode
(co jest tak naprawdę tylko formą testowania równości), ale nie wszystkie obiekty będą musiały mieć pojęcie uporządkowania , do czego sięcompareTo
to stosuje.źródło
Equitable<T>
ale gdyby zostałObject
zaimplementowany, każda klasa byłabyEquitable<Object>
. Czy w tym momencie jest jakaś różnica? W rzeczywistości niezupełnie, ze złożonością tak.object
maEquals(object)
, podobnie jak w Javie, ale istnieje równieżIEquatable<T>
interfejs. Chociaż głównym powodem jego istnienia jest unikanie boksowania, gdyT
jest to typ wartości, co nie jest możliwe w Javie.equals
jest zadeklarowanyObject
bezpośrednio:The methods equals and hashCode are declared for the benefit of hashtables such as java.util.Hashtable (§21.7)
- jako projekt Java jest kompatybilny z poprzednimi wersjami, wybór projektu Java 1.0 jest faktycznym powodem, abyequals
być tam, gdzie jest.Oprócz doskonałej odpowiedzi Bałwana pamiętaj, że
Comparable
od dawna jest to ogólny interfejs. Typ nie implementujecompareTo(object)
, implementujecompareTo(T)
gdzieT
jest swój własny typ. Nie można tego zaimplementowaćobject
, ponieważobject
nie zna klasy, która będzie z niego wyprowadzona.object
mógł zdefiniowaćcompareTo(object)
metodę, ale pozwoliłoby to nie tylko na to, co wskazuje Snowman, porównanie dwóchArrayList<T>
s lub dwóchThread
s, ale nawet porównanie międzyArrayList<T>
a aThread
. To jeszcze bardziej bezsensowne.źródło
Załóżmy, że mam dwa odwołania do obiektów: X identyfikuje instancję
String
przechowywania zawartości „George”; Y identyfikuje przykładPoint
trzymania współrzędnych [12,34]. Rozważ następujące dwa pytania:Czy X i Y identyfikują równoważne obiekty?
Czy X powinien sortować przed, po, czy może być równoważny Y?
Fakt, że X i Y identyfikują przypadki niepowiązanych typów, nie stanowi żadnego problemu przy rozważaniu pierwszego pytania. Obiekty można uznać za równoważne tylko wtedy, gdy ich typy mają wspólną bazę, która określa je jako równoważne; ponieważ
String
iPoint
nie mają takiej bazy (ich jedyny wspólny typ bazy uznaje wszystkie odrębne obiekty za równoważne) odpowiedź brzmi po prostu „nie”.Fakt, że typy nie są ze sobą powiązane, stanowi jednak ogromny problem w odniesieniu do drugiego pytania. Niektóre rodzaje definiować relacje zamawiania wśród swoich wystąpień, a niektóre relacje Zamawiający może nawet rozciągać na wiele typów [np byłoby możliwe
BigInteger
iBigDecimal
zdefiniowanie metod porównawczych, które pozwoliłyby wystąpienia dowolnego typu, aby zostać sklasyfikowanym w stosunku do wystąpień drugi], ale generalnie nie jest możliwe, aby wziąć dwie arbitralne instancje i zapytać „Czy X posortuje przed, po lub jako równoważnik Y” i uzyskać całkowite uporządkowanie. Można by zapytać „Czy X powinien sortować przed, po, równoważny lub nierankingowany względem Y”, czy obiekty muszą zgłaszać spójne uporządkowanie, ale nie całkowitejeden, ale większość algorytmów sortowania wymaga całkowitego uporządkowania. Zatem nawet jeśli wszystkie obiekty mogłyby zaimplementowaćcompareTo
metodę, jeśli „nierankowany” był prawidłowym zwrotem, taka metoda nie byłaby na tyle użyteczna, aby uzasadnić jej istnienie.źródło