I am studying Overriding hashCode() and equals(Object obj) methods of Object class.
body of equals(Object obj) method in Object class is :
public boolean equals(Object obj) {
return (this == obj);
}
and hashCode() is native :
public native int hashCode();
I have a class Test with overrided equals(Object obj) and hashCoe() :
public class Test {
public static void main(String[] args){
Test t1 = new Test();
Test t2 = new Test();
System.out.println("t1 toString() : " + t1.toString());
System.out.println("t1, Hex value of hashcode : " + Integer.toHexString(t1.hashCode()));
System.out.println("t2 toString() : " + t2.toString());
System.out.println("t2, Hex value of hashcode : " + Integer.toHexString(t2.hashCode()));
System.out.println(t1.equals(t2));
}
#Override
public int hashCode() {
return 999; //hard coded value is just for testing
}
#Override
public boolean equals(Object obj) {
return (this == obj);
}
}
Output of my Code is :
t1 toString() : demo.Test#3e7
t1, Hex value of hashcode : 3e7
t2 toString() : demo.Test#3e7
t2, Hex value of hashcode : 3e7
false //why it is false
why equals(Object obj) returns false in this case if both objects toString() returns the same reference ID (hashcode) [I am not sure if it compares hashcode or not].
What does == operator actually compare in case of objects?
in this answer, answerer said that == that is, it returns true if and only if both variables refer to the same object, if their references are one and the same.
How does it know that the variables refer to the same object???
How does it know that the variables refer to the same object?
Because the values of the variables are the same references. (Your variables are t1 and t2. The values of those variables are references. Those references are used as a way of navigating to objects, basically.)
Suppose you and I both have pieces of paper with a house's street address on (that's my usual analogy for "variables with references"). How do we check whether they refer to the same house? We see whether the address is the same.
There are some potential twists here, as in some cases the form of the reference may not be the same between two expressions, but that's the basic idea.
(Note that just because I've used "address" in the analogy, that doesn't mean a Java reference is always a memory address. It's "a way of navigating to an object", that's all. It may or may not just be an address.)
From the JVM specification section 2.2:
The Java Virtual Machine contains explicit support for objects. An object is either a dynamically allocated class instance or an array. A reference to an object is considered to have Java Virtual Machine type reference. Values of type reference can be thought of as pointers to objects. More than one reference to an object may exist. Objects are always operated on, passed, and tested via values of type reference.
== will check if both references are the same. You have 2 different objects, no matter they are equivalent, they point to different memory blocks.
The only exception to this rule is String, in special conditions(i.e. invoking .intern() method), but that's really a special case, related to String pool.
If you compare with == equals, the instances of the Object needs to be the same (pointer to the same reference, "same id" in the JVM). The hashcode of the object is'nt checked.
This is why it is a good practice to compare with equals(..) in Java.
Here some code:
Test o1 = new Test();
Test o2 = new Test();
//You can check the ids with System#identityHashCode(Object):
System.out.println(System.identityHashCode(o1));
System.out.println(System.identityHashCode(o2));
o1 == o1 // will be true
o1 == o2 // will be false
o1.equals(o2) //depends on how you have implemented equals() and hashCode() in the Test Object.
The contract between hashCode and Equals is:
objects which are .equals() must have the same .hashCode()
The reverse statement does not need to be true.
In your example, it is exacly the case: you return 999 in .hashCode() and you compare the jvm ids in .equals().
== checks to see if the two objects refer to the same place in memory. In other words, it checks to see if the 2 object names are basically references to the same memory location
EX1:
String obj1 = new String("xyz");
String obj2 = new String("xyz");
obj1==obj2; //False
EX2
String obj1 = new String("xyz");
String obj2 = obj1;
obj1==obj2; //True
Related
I was learning about Reference (or Address) comparison and Content comparison. The below statement makes me confused:
If a class does not override the equals method, then by default, it uses the equals(Object o) method of the closest parent class that has overridden this method.
Point to note: I haven't overridden the .equals() method and I'm only practicing it in my main class.
Below is my code:
package com.reference.content.comparison;
public class ReferenceAndContentComparison {
public static void main(String[] args) {
/* "==" operator is used for REFERENCE (or address) comparison. It means, it check if both objects point to same memory location or not.
* ".equals()" method is used for CONTENT comparison (in String class). It means, it check if both objects have same value or not.
*
* MAIN DIFFERENCES ARE:
* 1. "==" is an operator while ".equals()" is a method (of Object class).
* 2. Line 7 to 8.
* 3. ".equals()" method of Object class is used for REFERENCE comparison but in String class, it is used for CONTENT reference (by overriding .equals()).
* 4. If a class does not override the equals method, then by default, it uses the equals(Object o) method of the closest parent class that has overridden this method.
* 5. When comparing two Strings using .equals() method, their content is compared, and not their references.
* Link for point 5: https://docs.oracle.com/javase/8/docs/api/java/lang/String.html#equals-java.lang.Object-
*/
String s1 = "HELLO";
String s2 = "HELLO"; // references s1
String s3 = new String("HELLO"); // new instance but same content
System.out.println(s1 == s2); // true; Both s1 and s2 refer to same objects. Their addresses are same.
System.out.println(s1 == s3); // false; Addresses of s1 and s3 are different.
System.out.println(s1.equals(s2)); // true; Content of both s1 and s2 are same. Content Reference, because s1 and s2 are string class objects.
System.out.println(s1.equals(s3)); // true; Content of both s1 and s3 are same. Content Reference, because s1 and s3 are string class objects.
System.out.println("-----");
Thread t1 = new Thread();
Thread t2 = new Thread();
Thread t3 = t1;
String st1 = new String("WORLD");
String st2 = new String("WORLD");
System.out.println(t1 == t3); // true; Both t1 and t3 refer to same objects. Address of t1 is assigned to t3.
System.out.println(t1 == t2); //false; Addresses of t1 and t2 are different.
System.out.println(st1 == st2); // false; Addresses of st1 and st2 are different.
System.out.println(t1.equals(t2)); /* false; Here, t1 and t2 are both Thread class objects (not String class objects) and we haven't overridden the
.equals() method for Thread class anywhere so by default (as per point 4), .equals() of Object class will be
in effect and hence as per point 3, .equals() will be used as REFERNCE Comparison.
And since addresses are different, it's false.*/
System.out.println(st1.equals(st2)); /* true; Unlike above scenario, st1 and st2 are String class objects and hence as per point 5, content reference is
happening here and since their contents are same, it is true.*/
}
}
My confusion is that this t1.equals(t2) gives false because of which reason? Is it because the contents are not matching or reference comparison is happening here? I'm sure that the answer is Reference Comparison since I haven't overridden the .equals() method in my main class and by default it is using the method of the Object class (as stated in the statement at the very beginning).
But consider the below scenario too:
st1.equals(st2) is giving true because of which reason? Contents are matching? Is it not like reference comparison is happening here as well? Or, since contents are matching, it is not a reference comparison but a content comparison? Or, something else?
Please explain.
The String class overrides the equals method that is inherited from the Object class and implemented logic to compare the two String objects character by character.
Why you might ask, did the String class override the equals method inherited from the Object class? Because the equals method inherited from Object performs reference equality!
That's why when comparing two Strings using .equals() method, their content is compared, and not their references.
The evidence is provided by your code itself.
Here are two more pieces of evidence the String overrides the Object.equals(Object)
The Javadoc implies so. Notice that equality is based on the contents of the string. Indeed, even the existence of a distinct Javadoc for the String.equals(Object) method implies that the method has been overloaded ... given the way that javadocs are generated.
The source code says so. Clearly, the linked code is an overload. And clearly, it is not simply comparing object references.
Note
As commented, not all Strings in Java are interned. Try reading something from a file or console, those Strings aren't "interned", thus equals() (and also hashcode()) needs to be overridden.
This question already has answers here:
What is the difference between == and equals() in Java?
(26 answers)
Closed 9 years ago.
The equals method compares whether two object values are equal or not. My question is how it compares the two objects? How can it tell the two objects are equal or not? I want to know based on what it compares the two objects. I am not including the hashCode method.
The default implementation, the one of the class java.lang.Object, simply tests the references are to the same object :
150 public boolean equals(Object obj) {
151 return (this == obj);
152 }
The reference equality operator is described like this in the Java Specification :
At run time, the result of == is true if the operand values are both
null or both refer to the same object or array; otherwise, the result
is false.
This default behavior isn't usually semantically satisfying. For example you can't test equality of big Integer instances using == :
Integer a = new Integer(1000);
Integer b = new Integer(1000);
System.out.println(a==b); // prints false
That's why the method is overridden :
722 public boolean equals(Object obj) {
723 if (obj instanceof Integer) {
724 return value == ((Integer)obj).intValue();
725 }
726 return false;
727 }
which enables this :
System.out.println(a.equals(b)); // prints true
Classes overriding the default behavior should test for semantic equality, based on the equality of identifying fields (usually all of them).
As you seem to know, you should override the hashCode method accordingly.
Consider following example,
public class Employee {
String name;
String passportNumber;
String socialSecurityNumber;
public static void main(String[] args) {
Employee e1 = new Employee();
Employee e2 = new Employee();
boolean isEqual = e1.equals(e2); // 1
System.out.println(isEqual);
}
}
In the code at comment //1 it calls inherited equals method from Object class which is simply comparing references of e1 and e2. So it will always give false for each object created by using new keyword.
Following is the method excerpt from Object
public boolean equals(Object obj) {
return (this == obj);
}
For comparing equality check JLS has given equals method to override in our class. It is not final method. JLS doesn't know on what basis programmar wants to make two objects equal. So they gave non-final method to override.
hashcode does not play role to check object's equality. hashcode checks/finds the Bucket where object is available. we use hashcode in hashing technique which is used by some classes like HashMap..
If two object's hashcode are equals that doesn't means two objects are equal.
For two objects, if equals method returns true then hashcode must be same.
You will have to override equals method to decide on which basis you want object e1 and e2 in above code is equal. Is it on the basis of passportNumber or socialSecurityNumber or the combination of passportNumber+socialSecurityNumber?
I want to know based on what it compares the two objects.
Answer is, by default with the help of inherited Object class's equals method it compares two object's reference equality by using == symbol. Code is given above.
logically, equals does not compare objects (however you can do anything with it), it compares values. for object comparison there is '==' operator
I constructed a class with one String field. Then I created two objects and I have to compare them using == operator and .equals() too. Here's what I've done:
public class MyClass {
String a;
public MyClass(String ab) {
a = ab;
}
public boolean equals(Object object2) {
if(a == object2) {
return true;
}
else return false;
}
public boolean equals2(Object object2) {
if(a.equals(object2)) {
return true;
}
else return false;
}
public static void main(String[] args) {
MyClass object1 = new MyClass("test");
MyClass object2 = new MyClass("test");
object1.equals(object2);
System.out.println(object1.equals(object2));
object1.equals2(object2);
System.out.println(object1.equals2(object2));
}
}
After compile it shows two times false as a result. Why is it false if the two objects have the same fields - "test"?
== compares object references, it checks to see if the two operands point to the same object (not equivalent objects, the same object).
If you want to compare strings (to see if they contain the same characters), you need to compare the strings using equals.
In your case, if two instances of MyClass really are considered equal if the strings match, then:
public boolean equals(Object object2) {
return object2 instanceof MyClass && a.equals(((MyClass)object2).a);
}
...but usually if you are defining a class, there's more to equivalency than the equivalency of a single field (a in this case).
Side note: If you override equals, you almost always need to override hashCode. As it says in the equals JavaDoc:
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.
You should override equals
public boolean equals (Object obj) {
if (this==obj) return true;
if (this == null) return false;
if (this.getClass() != obj.getClass()) return false;
// Class name is Employ & have lastname
Employe emp = (Employee) obj ;
return this.lastname.equals(emp.getlastname());
}
The best way to compare 2 objects is by converting them into json strings and compare the strings, its the easiest solution when dealing with complicated nested objects, fields and/or objects that contain arrays.
sample:
import com.google.gson.Gson;
Object a = // ...;
Object b = //...;
String objectString1 = new Gson().toJson(a);
String objectString2 = new Gson().toJson(b);
if(objectString1.equals(objectString2)){
//do this
}
The overwrite function equals() is wrong.
The object "a" is an instance of the String class and "object2" is an instance of the MyClass class. They are different classes, so the answer is "false".
It looks like equals2 is just calling equals, so it will give the same results.
Your equals2() method always will return the same as equals() !!
Your code with my comments:
public boolean equals2(Object object2) { // equals2 method
if(a.equals(object2)) { // if equals() method returns true
return true; // return true
}
else return false; // if equals() method returns false, also return false
}
The "==" operator returns true only if the two references pointing to the same object in memory. The equals() method on the other hand returns true based on the contents of the object.
Example:
String personalLoan = new String("cheap personal loans");
String homeLoan = new String("cheap personal loans");
//since two strings are different object result should be false
boolean result = personalLoan == homeLoan;
System.out.println("Comparing two strings with == operator: " + result);
//since strings contains same content , equals() should return true
result = personalLoan.equals(homeLoan);
System.out.println("Comparing two Strings with same content using equals method: " + result);
homeLoan = personalLoan;
//since both homeLoan and personalLoan reference variable are pointing to same object
//"==" should return true
result = (personalLoan == homeLoan);
System.out.println("Comparing two reference pointing to same String with == operator: " + result);
Output:
Comparing two strings with == operator: false
Comparing two Strings with same content using equals method: true
Comparing two references pointing to same String with == operator: true
You can also get more details from the link: http://javarevisited.blogspot.in/2012/12/difference-between-equals-method-and-equality-operator-java.html?m=1
Statements a == object2 and a.equals(object2) both will always return false because a is a string while object2 is an instance of MyClass
Your implementation must like:
public boolean equals2(Object object2) {
if(a.equals(object2.a)) {
return true;
}
else return false;
}
With this implementation your both methods would work.
If you dont need to customize the default toString() function, another way is to override toString() method, which returns all attributes to be compared. then compare toString() output of two objects. I generated toString() method using IntelliJ IDEA IDE, which includes class name in the string.
public class Greeting {
private String greeting;
#Override
public boolean equals(Object obj) {
if (this == obj) return true;
return this.toString().equals(obj.toString());
}
#Override
public String toString() {
return "Greeting{" +
"greeting='" + greeting + '\'' +
'}';
}
}
Your class might implement the Comparable interface to achieve the same functionality. Your class should implement the compareTo() method declared in the interface.
public class MyClass implements Comparable<MyClass>{
String a;
public MyClass(String ab){
a = ab;
}
// returns an int not a boolean
public int compareTo(MyClass someMyClass){
/* The String class implements a compareTo method, returning a 0
if the two strings are identical, instead of a boolean.
Since 'a' is a string, it has the compareTo method which we call
in MyClass's compareTo method.
*/
return this.a.compareTo(someMyClass.a);
}
public static void main(String[] args){
MyClass object1 = new MyClass("test");
MyClass object2 = new MyClass("test");
if(object1.compareTo(object2) == 0){
System.out.println("true");
}
else{
System.out.println("false");
}
}
}
the return type of object.equals is already boolean.
there's no need to wrap it in a method with branches. so if you want to compare 2 objects simply compare them:
boolean b = objectA.equals(objectB);
b is already either true or false.
When we use == , the Reference of object is compared not the actual objects. We need to override equals method to compare Java Objects.
Some additional information C++ has operator over loading & Java does not provide operator over loading.
Also other possibilities in java are implement Compare Interface .which defines a compareTo method.
Comparator interface is also used compare two objects
Here the output will be false , false beacuse in first sopln statement you are trying to compare a string type varible of Myclass type to the other MyClass type and it will allow because of both are Object type and you have used "==" oprerator which will check the reference variable value holding the actual memory not the actual contnets inside the memory .
In the second sopln also it is the same as you are again calling a.equals(object2) where a is a varible inside object1 . Do let me know your findings on this .
In short, == compares two POINTERS.
If the two pointers are equal, then they both point to same object in memory (which, obviously has the same value as itself).
However, .equals will compare the VALUES of whatever is pointed to, returning true iff they both evaluate to the same value.
Thus, two separate strings (i.e., at different addresses in memory) are always != but are .equal iff they contain the same (null-terminated) sequence of chars.
IN the below code you are calling the overriden method .equals().
public boolean equals2(Object object2) {
if(a.equals(object2)) { // here you are calling the overriden method, that is why you getting false 2 times.
return true;
}
else return false;
}
I am looking at the equals method, and I see this and I don't understand what it means...I do understand them when I see it in constructors and some methods but its not clear to me when they are in equals method something like this:
(obj == this) ...what does this mean here ? where does it come from ?
I understand when it says something like this.name = name;
from a method like this
#Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if (obj == null || obj.getClass() != this.getClass()) {
return false;
}
sorry it might be a duplicate but I couldnt find anything...
this is the current Object instance. Whenever you have a non-static method, it can only be called on an instance of your object.
You are comparing two objects for equality. The snippet:
if (obj == this) {
return true;
}
is a quick test that can be read
"If the object I'm comparing myself to is me, return true"
. You usually see this happen in equals methods so they can exit early and avoid other costly comparisons.
You have to look how this is called:
someObject.equals(someOtherObj);
This invokes the equals method on the instance of someObject. Now, inside that method:
public boolean equals(Object obj) {
if (obj == this) { //is someObject equal to obj, which in this case is someOtherObj?
return true;//If so, these are the same objects, and return true
}
You can see that this is referring to the instance of the object that equals is called on. Note that equals() is non-static, and so must be called only on objects that have been instantiated.
Note that == is only checking to see if there is referential equality; that is, the reference of this and obj are pointing to the same place in memory. Such references are naturally equal:
Object a = new Object();
Object b = a; //sets the reference to b to point to the same place as a
Object c = a; //same with c
b.equals(c);//true, because everything is pointing to the same place
Further note that equals() is generally used to also determine value equality. Thus, even if the object references are pointing to different places, it will check the internals to determine if those objects are the same:
FancyNumber a = new FancyNumber(2);//Internally, I set a field to 2
FancyNumber b = new FancyNumber(2);//Internally, I set a field to 2
a.equals(b);//true, because we define two FancyNumber objects to be equal if their internal field is set to the same thing.
this refers to the current instance of the class (object) your equals-method belongs to. When you test this against an object, the testing method (which is equals(Object obj) in your case) will check wether or not the object is equal to the current instance (referred to as this).
An example:
Object obj = this;
this.equals(obj); //true
Object obj = this;
new Object().equals(obj); //false
I am digging into the basics of Java. I infer from this article, that the Java 'equals' method means, if two objects are equal then they must have the same hashCode().
Here's my example.
public class Equals {
/**
* #param args
*/
public static void main(String[] args) {
String a = new String("a");
String b = new String("a");
System.out.println("a.hashCode() "+a.hashCode());
System.out.println("b.hashCode() "+b.hashCode());
System.out.println(a == b);
System.out.println(a.equals(b));
}
}
Output:
a.hashCode() 97
b.hashCode() 97
false
true
The actual Java language 'equals' method:
public boolean equals(Object obj) {
return (this == obj);
}
In my above example, a.equals(b) has returned true, meaning the condition 'a==b' is satisfied. But then why is 'a==b' returning false in that example?
Aren't hashCode and address one and same? Also, is 'hashCode' compared when we say 'a==b' or something else?
The String class has overridden the equals() method. Please follow the String equals() documentation.
a.equals(b) has returned true, meaning the condition a==b is satisfied
This is the default implementation of equals() in the Object class, and the String class has overridden the default implementation. It returns true if and only if the argument is not null and is a String object that represents the same sequence of characters as this object.
Aren't hashCode and address one and same?
Not necessarily. For further reading on hashCode().
The == operator in Java compares object references to see if they refer to the same object. Because your variables a and b refer to different objects, they are not equal according to ==.
And the hashCode method doesn't return the address in String, because that class has overridden hashCode.
Additionally, the equals method has been implemented in String to compare the contents of the strings; that's why a.equals(b) returns true here.
No, Hashcode and address aren't the same.
Because a==b is not comparing hashcodes.
Yes, something else is compared when we say a==b.
(that's not addresses either, really, but it's close enough).
Also, just because "equal objects have equal hashcodes" does not mean "equal hashcodes means equal objects".
a.equals(b) is different from a==b.
a.equals(b) checks if two objects are equals based on equals() implementation.
a==b checks if two objects have same reference.
If a==b is true then a.equals(b) must be true because they are referencing to the same object but not vice-versa.
String class overrides the default implementation of the equals() method of the Object class. The equals method code that you have provided is not from String class but from the Object class, which is overridden be the String class implementation which checks if the contents of the two objects are same or not.
Hashcode for an object is meant to be overridden.
For String class the formula used is as follows:
s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]
I encourage you to search why 31 has been used as a multiplier and not some other number.
A general thumb rule for overriding hash code is that for different objects hash code should be different as far as possible.
To achieve this it is advisable that you take into account every significant field of an object while calculating the hash value.
Note: Just an unrelated food for thought (source : Effective Java):
Consider the following implementation of hashcode
int hashcode(){
return 10;
}
This is a valid implementation but it is also the worst possible one. Read about why.
A and B are two separate objects that generate the same hash code because of String's implementation of hashCode(). == just checks to see if the left and right sides share the same reference. It does not call an Object's equals() method.
So, no, hashes and object references are not the same thing.
public class TestEquals {
/**
* #param args
*/
public static void main(String[] args) {
String a = new String("a");
String b = new String("a");
System.out.println("a.hashCode() " + a.hashCode());
System.out.println("b.hashCode() " + b.hashCode());
// Checks the reference which is something like the
// address & address is different from hash code which can be overriden
System.out.println(a == b);
// It returns true if and only if the argument is not null
// and is a String object that represents the same sequence
// of characters as this object. (String Implementation of equals)
System.out.println(a.equals(b));
}
}
Output:
a.hashCode() 97
b.hashCode() 97
false
true