When writing one's own classes, is it always necessary to override equals(Object o)?
If I don't, will it automatically check that all the fields are the same? Or does it just check if the two variables point to the same object?
If one is writing a class that is going to have its objects be compared in some way, then one should override the equals and hashCode methods.
Not providing an explicit equals method will result in inheriting the behavior of the equals method from the superclass, and in the case of the superclass being the Object class, then it will be the behavior setforth in the Java API Specification for the Object class.
The general contract for providing an equals method can be found in the documentation for the Object class, specifically, the documentation of the equals and hashCode methods.
Only override equals() if it makes sense. But obviously if you override equals() you need to ensure that the hashcode() contract isn't broken, meaning if two objects are equal they must have the same hash code.
When does it make sense? When Object.equals() is insufficient. That method basically comes down to reference identity, meaning two objects are the same object so:
a.equals(b) iff q == b
Numbers are an obvious example when it makes sense because Integer(10) should equal another Intger(10).
Another example could be when you're representing database records. Let's say you have Student records with a unique integer ID, then it might be sufficient implementation of equals to simply compare the ID fields.
The equals method for class Object implements the most discriminating possible equivalence relation on objects; that is, for any non-null reference values x and y, this method returns true if and only if x and y refer to the same object (x == y has the value true).
To test whether two objects are equal in the sense of equivalency (containing the same information), you must override the equals() method.You should always override the equals() method if the identity operator is not appropriate for your class.
Note that it is generally necessary to override the hashCode method whenever this method is overridden, so as to maintain the general contract for the hashCode method, which states that equal objects must have equal hash codes.
While you shouldn't rely on an IDE, Eclipse provides this canned functionality by pressing alt + shift + s and selecting the equals and hashCode menu options. There is also a toString option. Effective Java by Josh Bloch has good info on this subject. The link will take you to the chapter hosted on Google Books that discusses this topic.
Related
When using lombok #Data (which adds EqualsAndHashCode)
It adds canEqual method
protected boolean canEqual(Object other) {
return other instanceof Exercise;
}
which is only called once:
if (!other.canEqual((Object)this)) return false;
I search and found discussions about access level
If you implement equals and hashCode in a non-final class the safest thing we can do is add the can equal the way we do. Since we don't add any field the costs, especially if the method is protected, are slim.
But why do we need this generated method ? can't it be inline?
The canEqual method is defined in a paper entitled How to Write an Equality Method in Java. This method is meant for allowing to redefine equality on several levels of the class hierarchy while keeping its contract:
The idea is that as soon as a class redefines equals (and hashCode), it should also explicitly state that objects of this class are never equal to objects of some superclass that implement a different equality method. This is achieved by adding a method canEqual to every class that redefines equals.
Seems like it was introduced in Lombok 0.10, as described in the #EqualsAndHashCode documentation:
NEW in Lombok 0.10: Unless your class is final and extends java.lang.Object, lombok generates a canEqual method which means JPA proxies can still be equal to their base class, but subclasses that add new state don't break the equals contract.
And the documentation goes a bit further, referencing the paper quoted above:
The complicated reasons for why such a method is necessary are explained in this paper: How to Write an Equality Method in Java. If all classes in a hierarchy are a mix of scala case classes and classes with lombok-generated equals methods, all equality will 'just work'. If you need to write your own equals methods, you should always override canEqual if you change equals and hashCode.
Why does the Collection interface have equals(Object o) and hashCode(), given that any implementation will have those by default (inherited from Object) ?
From the Collection JavaDoc:
While
the Collection interface adds no stipulations to the general contract
for the Object.equals, programmers who implement the Collection
interface "directly" (in other words, create a class that is a
Collection but is not a Set or a List) must exercise care if they
choose to override the Object.equals. It is not necessary to do so,
and the simplest course of action is to rely on Object's
implementation, but the implementor may wish to implement a "value
comparison" in place of the default "reference comparison." (The List
and Set interfaces mandate such value comparisons.)
The general contract for the Object.equals method states that equals
must be symmetric (in other words, a.equals(b) if and only if
b.equals(a)). The contracts for List.equals and Set.equals state that
lists are only equal to other lists, and sets to other sets. Thus, a
custom equals method for a collection class that implements neither
the List nor Set interface must return false when this collection is
compared to any list or set. (By the same logic, it is not possible to
write a class that correctly implements both the Set and List
interfaces.)
and
While the Collection interface adds no stipulations to the general contract for the Object.hashCode method, programmers should take note that any class that overrides the Object.equals method must also override the Object.hashCode method in order to satisfy the general contract for the Object.hashCode method. In particular, c1.equals(c2) implies that c1.hashCode()==c2.hashCode().
To answer your specific question: why does it have these methods? It's done simply for convenience to be able to include Java Docs giving hints as to what implementers should do with these methods (e.g. comparing equality of values rather than references).
To add to the other great answers. In the Collections interface, the equals method is defined in that interface to make some decisions in the way equaling two instances of collection should work. From the JAVA 8 documentation:
More generally, implementations of the various Collections Framework
interfaces are free to take advantage of the specified behavior of
underlying Object methods wherever the implementor deems it
appropriate.
So you don’t add methods from the Object class for any other reason that giving more definitiveness to the java doc. This is the reason why you don’t count those methods in the abstract methods in the abstract methods of an interface.
Moreover, in JAVA 8, along the same line of reasoning, default methods from the Object class are not allowed and will generate a compile error. I believe it’s was done to prevent this type of confusion. So if you try to create a default method called hashCode(), for example, it will not compile.
Here is a more in-depth explanation for this behavior in JAVA 8 from the Lambda FAQ:
An interface cannot provide a default implementation for any of the
methods of the Object class. This is a consequence of the “class wins”
rule for method resolution: a method found on the superclass chain
always takes precedence over any default methods that appear in any
superinterface. In particular, this means one cannot provide a default
implementation for equals, hashCode, or toString from within an
interface.
This seems odd at first, given that some interfaces actually define
their equals behavior in documentation. The List interface is an
example. So, why not allow this?
One reason is that it would become more difficult to reason about when
a default method is invoked. The current rules are simple: if a class
implements a method, that always wins over a default implementation.
Since all instances of interfaces are subclasses of Object, all
instances of interfaces have non-default implementations of equals,
hashCode, and toString already. Therefore, a default version of these
on an interface is always useless, and it may as well not compile.
Another reason is that providing default implementations of these
methods in an interface is most likely misguided. These methods
perform computations over the object’s state, but the interface, in
general, has no access to state; only the implementing class has
access to this state. Therefore, the class itself should provide the
implementations, and default methods are unlikely to be useful.
Just to add to the great answers above, it makes sense to have the 'equals' or `hashCode' methods in this scenario:
Collection<Whatever> list1 = getArrayList();
Collection<Whatever> list2 = getAnotherArrayList();
if(list1.equals(list2)){
// do something
}
In the absence of the equals method in the interface, we'll be forced to use concrete types, which is generally not a good practice :
ArrayList<Whatever> list1 = getArrayList();
ArrayList<Whatever> list2 = getAnotherArrayList();
if(list1.equals(list2)){
// do something
}
I want to override equals(Object o) without using instanceof, getClass() and casting. Is this doable in Java and if yes how it is possiable?
Editing: And I want to use this method too.
For example: I want to override this method in class Cow and use it to check if my Cow logically equals to other Cow?
Thanks for answers everyone. My main problem is that: what happens if I send Car as other class to my cow or any other Object. How can I check if Object o got method getName() (Assuming my Cow got this method)?
Sure.
Make Cow serializable, and make sure that its serialized form is canonical (worst case by implementing Externalizable and hand-writing your own serialization that is canonical) and then do the following in equals:
Try to serialize the argument. If that fails, return false.
Serialize this.
Compare the serialized bytes of the two.
Since the serial form includes a string identifying the type, it includes the bytes necessary to distinguish instances of different types.
This isn't easy, is inefficient, is probably a maintenance nightmare, and should definitely not be your first choice, but it does demonstrate that there are language tricks available to Java code that will allow type distinction without instanceof or Class sameness checks.
One caveat though: the serial form does not distinguish between classes with the same name loaded in different class loaders.
It's certainly possible if the criteria for equality are limited to using information that is only available from an Object.
This /seems/ unlikely... why would you be overriding equals if you were only using Object's methods? However, there's nothing to prevent you from doing it, if this is appropriate for your design.
Just be sure that you maintain the contract defined in the Javadocs for equals()
The Comparator interface has its own equals() method. Any class will get equals() by default through Object class. What is the need to have equals() method inside an interface?
Comparator refines the contract of Object.equals: It has to satisfy the constraints set out by Object.equals and then some.
Additionally, this method can return true only if the specified object is also a comparator and it imposes the same ordering as this comparator. Thus, comp1.equals(comp2) implies that sgn(comp1.compare(o1, o2))==sgn(comp2.compare(o1, o2)) for every object reference o1 and o2.
Declaring an equals inside Comparator allows you to document this in the form of javadoc.
Note that the documentation of the API also serves as the contract, so it's not just cosmetics here. It's explicit constraints that other code and your code can rely on.
In similar situations where you have less established methods, it may also serve as documenting an intent. I.e., Interface.method should be there, regardless of how its super interfaces evolves.
From the Java documentations, the reason why Comparator has it's own equals() method:
However, overriding this method may, in some cases, improve performance by allowing programs to determine that two distinct comparators impose the same order.
Read its javadoc. It's there only to explain what equals() must return if you choose to override it in a class implementing Comparator. You might think that no comparator can be equal to any other, but it's not the case. You might think that two comparators are equal if they return the same thing for any arguments, but it's not the case. The javadoc explains that two comparators are equal if they impose the same ordering, whatever the arguments given. The javadoc also says:
Note that it is always safe not to override Object.equals(Object)
Most of the time, you don't override equals() in comparators.
from the docs:
it is always safe not to override Object.equals(Object). However, overriding this method may, in some cases, improve performance by allowing programs to determine that two distinct comparators impose the same order.
Technically, the declaration of the method is redundant (the compiler does not care), but...
Declaring the equals method in this interface makes it part of the contract between caller and different Comparators and allows it to specify/extend its semantics.
It specifies that two Comparators are equal only if they impose the same ordering with their compare() method. This extends the semantics of Object.equals() and must therefore be documented in the interface.
Putting an Object method in an interface declaration allows Javadoc
declaration of the meaning equals is required to have in classes that
implement the interface.
Comparator interface have their own equals() method
Well,. first of all, it should be clear that whenever you implement Comparable interface you should provide your program to decide when objects are equal, less or greater.
I am quite confuse about have equals() inside Comparator. Any class will get equals() by default through Object class.
The equals() method implementation u inherit from Object class only checks whether the two referances point to the same object or not. It dosn't apply any comparison. It's you who will provide in your class (or possibly in your Interface) the criteria for objects to be equal.
Then what is need to have equals() method inside an interface?
Obviously , whenever you implement when objects are less , greater than you must implement when they are equal. so rather than relying on default Object equals() method you should provide your logic to check equality
The equals() method in Comparator is provided to force a user implementing the Comparator interface to implement equals() with some additional rules and constraints in addition to the ones already applied on equals() from Object.
The additional rule being:
This method must obey the general contract of Object.equals(Object).
Additionally, this method can return true only if the specified object
is also a comparator and it imposes the same ordering as this
comparator. Thus, comp1.equals(comp2) implies that
sgn(comp1.compare(o1, o2))==sgn(comp2.compare(o1, o2)) for every
object reference o1 and o2.
I have a class Dog extends Animal.
Then I call the hashCode() method as follows.
Animal animal = new Dog(200);
System.out.println(animal.hashCode());
Here,
If I've overridden the hashCode() in the Dog class it will be returned.
Else if I've overridden the hashCode() in the Dog class it will be returned.
Else some integer returned.
I wanna know...
Why does it call the hashCode() of the super class when it is not
overriden in the Dog class? How and what the 'some integer' generated
When the hashCode is not generated in anywhere. (I have heard that it
is the memory location of the object but not sure.)
This is referred to as method overriding. The hashCode method is defined in java.lang.Object, basically the top of the object heirarchy, so it is always available to any Object defined in Java. If the method is not overriden in your specific subclass or one of its parents, the default behavior defined in java.lang.Object will be invoked.
You typically should not worry about what the internal implementation of a hash code is in a parent object, but the default implementation does use the internal address of the Object. Note that this internal address is precisely that - an interpreted address that the JVM uses internally, that should not be depended upon by an application to be anything particularly meaningful.
You can read more about how overriding works in the Java Language Specification - Section 8.4.8.
In java every class, if not explitcitly mentioned, will have Object class as its parent class. As Object class defines the hashcode method this is avilable even if you don't define in your class. And yes, in java the default hashcode implemention is to return the memory location of the object. In a way this looks correct way as if two object are at same memory location than they must be same.
hasCode() is form parent class object so if you haven't override it then parent method will be called. I think what you refer to as some integer is the hashCode generated at the super parent Object. Which suggest you haven't override the hashCode in Animal class.
In general if a super class method is not overridden then the immediate parent's method will be called.
First In java every class, if not explitcitly mentioned, will have Object class as its parent class
Java doesn't generate hashCode(), i.e. This is typically implemented by converting the internal address of the object into an integer, but this implementation technique is not required by the JavaTM programming language.
Most classes (especially if you are going to use it in any of the Collection API) specially in hashcontainer(HashSet and HashMap) should implement their own HashCode (and by contract their own equals method).
If you are interested to know when to implement hashCode() and equals() you can visit this site http://www.javabeat.net/2007/08/hashcode-and-equals-methods/