I want to know why the .compareTo()
is in the Comparable
interface while a method like .equals
is in the Object
class. To me, it seems arbitrary why a method like .compareTo()
is not in the Object
class already.
To use .compareTo()
, you implement the Comparable
interface and implement the .compareTo()
method for your purposes. For the .equals()
method, you simply override the method in your class, since all classes inherit from the Object
class.
My question is why is a method like .compareTo()
in an interface that you implement rather than in a class like Object
? Likewise, why is the .equals()
method in the class Object
and not in some interface to be implemented?
3
Not all objects can be compared, but all objects can be checked for equality. If nothing else, one can see if two objects exist at the same location in memory (reference equality).
What does it mean to compareTo()
on two Thread
objects? How is one thread “greater than” another? How do you compare two ArrayList<T>
s?
The Object
contract applies to all Java classes. If even one class cannot be compared to other instances of its own class, then Object
cannot require it to be part of the interface.
Joshua Bloch uses the key words “natural ordering” when explaining why a class might want to implement Comparable
. Not every class has a natural ordering as I mentioned in my examples above, so not every class should implement Comparable
nor should Object
have the compareTo
method.
…the
compareTo
method is not declared inObject
. … It is
similar in character toObject
‘sequals
method, except that it
permits order comparisons in addition to simple equality comparisons,
and it is generic. By implementingComparable
, a class indicates
that its instances have a natural ordering.
Effective Java, Second Edition: Joshua Bloch. Item 12, Page 62. Ellipses remove references to other chapters and code examples.
For cases where you do want to impose an ordering on a non-Comparable
class that does not have a natural ordering, you can always supply a Comparator
instance to help sort it.
13
The JLS §4.3.2 defines the class
object in the following way:
4.3.2. The Class Object
The class
Object
is a superclass (§8.1.4) of all other classes.All class and array types inherit (§8.4.8) the methods of class
Object
, which are summarized as follows:
The method
clone
is used to make a duplicate of an object.The method
equals
defines a notion of object equality, which is based on value, not reference, comparison.The method
finalize
is run just before an object is destroyed (§12.6).The method
getClass
returns the Class object that represents the class of the object.A
Class
object exists for each reference type. It can be used, for example, to discover the fully qualified name of a class, its members, its immediate superclass, and any interfaces that it implements.The type of a method invocation expression of
getClass
isClass<? extends |T|>
whereT
is the class or interface searched (§15.12.1) forgetClass
.A class method that is declared
synchronized
(§8.4.3.6) synchronizes on the monitor associated with the Class object of the class.The method
hashCode
is very useful, together with the method equals, in hashtables such asjava.util.Hashmap
.The methods
wait
,notify
, andnotifyAll
are used in concurrent programming using threads (§17.2).The method
toString
returns a String representation of the object.
So, that’s why equals
is in Object
but compareTo
is in a separate interface. I would speculate that they wanted to keep Object
as minimal as possible. They probably figured that nearly all Objects
would need equals
and hashCode
(which is really just a form of equality testing) but not all objects would need to have a concept of ordering, which is what compareTo
is used for.
6
In addition to Snowman’s excellent answer, remember that Comparable
has been a generic interface for a long time. A type doesn’t implement compareTo(object)
, it implements compareTo(T)
where T
is its own type. This cannot be implemented on object
, since object
does not know the class that will be derived from it.
object
could have defined an compareTo(object)
method, but this would have allowed not just what Snowman points out, a comparison between two ArrayList<T>
s or between two Thread
s, but even a comparison between an ArrayList<T>
and a Thread
. That’s even more nonsensical.
Suppose I have two object references: X identifies an instance of String
holding the content “George”; Y identifies instance of Point
holding the coordinates [12,34]. Consider the following two questions:
-
Do X and Y identify equivalent objects?
-
Should X sort before, after, or equivalent to Y?
The fact that X and Y identify instances of unrelated types does not pose any problem when considering the first question. Objects can only be considered equivalent if their types share a common base that defines them as being equivalent; since String
and Point
have no such base (their only common base type regards all distinct objects as non-equivalent) the answer is simply “no”.
The fact that the types are unrelated, however, poses a huge problem with regard to the second question. Some types define ordering relationships among their instances, and some ordering relationships may even extend over multiple types [e.g. it would be possible for BigInteger
and BigDecimal
to define comparison methods that would allow instances of either type to be ranked relative to instances of the other], but it is not possible in general to take two arbitrary instances and ask “Should X sort before, after, or equivalent to Y” and derive a total ordering. It would be possible to ask “Should X sort before, after, equivalent, or unranked with respect to Y” if objects were required to report a consistent ordering though not a total one, but most sorting algorithms require total orderings. Thus, even if all objects could implement a compareTo
method if “unranked” was a valid return, such a method wouldn’t be useful enough to justify its existence.