问题
I was learning hashcode in more depth and figured that:
1. If you override equals(), you must override hashcode() too.
2. To find if 2 objects are same object, use == operator
Given those 2 factors, in Java I was assuming that when == operator
is used to compare if 2 instances are same or not,
if(object1 == object2)
is actually doing
if(object1.hashcode() == object2.hashcode())
But it appears I was wrong by running the test below.
public class Main {
public static void main(String[] args){
Obj1 one = new Obj1();
Obj1 two = new Obj1();
//is this calling hashCode() in backend???
if(one == two) {
System.out.println("same");
}
else {
System.out.println("nope");
}
//this is of course return true
if(one == one) {
System.out.println("one and one is same");
}
}
}
class Obj1 {
@Override
public int hashCode() {
System.out.println("hashCode() is called");
return 111;
}
@Override
public boolean equals(Object another) {
System.out.println("equals() is called");
return false;
}
}
According to the test which uses == operator
and see if equals()
is called and it wasn't.
So my question is if == operator
can used to compare if the object is same or not, what is the point of overriding equals()
and hashCode()
method for comparison? Isn't == operator
do the job already?
reference:
Overriding hashCode() - is this good enough?
http://mindprod.com/jgloss/hashcode.html
http://download.oracle.com/javase/1.4.2/docs/api/java/lang/Object.html#equals(java.lang.Object)
回答1:
the == operator determines if 2 references point to the same object.
So
Object o1 = new Object();
Object o2 = o1;
o1 == o2; //true
o2 = new Object();
o1 == o2 // false
the Object.equals() method is "how do I determine if 2 references to objects, that are not the same object, are equal?"
If two references point to the same object, both
o1 == o2
o1.equals(o2)
should be true.
But if o1 and o2 are not the same object, they still might be equal logically. For any given class, equals depends on the semantics behind the object. For example, consider a class where field1 and field2 are set by the user, but field3 is computed and has a random element to its computation. It might make sense to define equals in this case to only depend on field1 and field2, and not field3. Thats why equals is necessary.
回答2:
==
is identity.
.equals()
is equality.
.equals()
defaults to just using ==
(just like hashCode()
defaults to System.identityHashCode()
but you can override them if there's a more meaningful way to check for equality. Typically this is a sort of "structural" equality. ie: are all of the pieces of this
.equal()
to all of the pieces of that
?
回答3:
If you don't already have a copy; buy a copy of Effective Java by Joshua Bloch.
This is the de facto reference for Java developers and has a lot of information on this (and many other) subject.
回答4:
==
(used on objects rather than on primitive values) tests whether 2 objects are actually the same object; it compares whether the pointers are actually pointing to the same memory location.
.equals()
is defined by the object itself.
String s1 = new String("Hello");
String s2 = new String("Hello");
boolean b1 = ( s1 == s2 ) ; // false: s1 and s2 point to different objects
boolean b2 = ( s1.equals(s2) ) ; // true: s1 and s2 both represent the same
// piece of text - "Hello"
.hashCode()
is an optimisation trick (in most of its uses, anyway). A lot of code in the standard libraries makes the assumption that if o1.equals(o2)==true
then o1.hashCode()==o2.hashCode()
and that if o1.hashCode()!=o2.hashCode()
then o1.equals(o2)==false
in order to work faster.
The most obvious example of such an optimisation is the HashMap class. This makes retrieving objects using a key really fast, but breaks badly if hashCode and equals don't work properly for the key elements. In fact, this is one of the reasons that the String class is immutable: if you were able to modify a String (and so change its hashCode) while that String was the key in a HashMap, then you would never be able to find it, since you would end up looking for it in the wrong place!
Other answers recommend Effective Java by Joshua Bloch. If you are asking such questions, then now is the perfect time in your career to buy the book and read it cover to cover. It'll also be worth re-reading it in a year or two's time, when you'll have forgotten some of it and more of it will make sense...
回答5:
Most is already answered, so here's just another enlightening example:
String s1 = "foo";
String s2 = "foo";
System.out.println(s1 == s2); // true, because same reference (string pool)
String s3 = new String("foo");
String s4 = new String("foo");
System.out.println(s3 == s4); // false, because different reference
System.out.println(s3.equals(s4)); // true, because same value
回答6:
==
operator --> checks weather 2 references point to the same object or not. If same it return true otherwise false.
equals( )
--> checks both reference and state object. Hear state means object data. In this any one is true it returns true. Otherwise false. But we have to override equals( )
in our user defined object and write the appropriate code.
Hashcode( )
-->hashCode of an Object just represents a random number which can be used by JVM while saving/adding Objects into Hashsets, Hashtables or Hashmap.
Example of hashcode()
class TestHasChode
{
int i;
TestHasChode(int i)
{
this.i = i;
}
public static void main(String arg[])
{
//before overriding hashcode()
TestHasChode t1 = new TestHasChode(100);
TestHasChode t2 = new TestHasChode(110);
System.out.println(t1); //TestHasChode@45e41830
System.out.println(t2); //TestHasChode@1f01b29
TestHasChode t3 = new TestHasChode(100);
TestHasChode t4 = new TestHasChode(100);
System.out.println(t3); //TestHasChode@3a8721bd
System.out.println(t4); //TestHasChode@7db81d4f
/*hashCode() of Object class implemented to return hashCode based on address of an object, but based
on our requirement we can override hashCode() to generate our own numbers as hashCodes*/
//after overriding hashcode()
System.out.println(t3); //TestHasChode@64
System.out.println(t4); //TestHasChode@64
}
public int hashCode(){
return i;
}
}
-->Example of equals()method
class Student
{
String name;
int rollno;
Student(String name,int rollno)
{
this.name = name;
this.rollno = rollno;
}
public static void main(String arg[])
{
//before overrideng equals method
Student s1 = new Student ("raju", 101);
Student s2 = new Student ("giri", 102);
Student s3 = new Student ("giri", 102);
System.out.println(s1.equals(s2));//false
System.out.println(s2.equals(s3));//false
//after overriding equals method
System.out.println(s1.equals(s2));//false
System.out.println(s2.equals(s3));//true-->hear overriding equals() checks state.so it is true.
//in string variables comparisition
String s4="hello";
String s5=new String("hello");
String s6=new String("hello");
System.out.println(s4.equals(s5));//true--> because String class containg overridden equals method
System.out.println(s5.equals(s6));//true-->even though differnet object reference but String class containg overridden equals method
}
public boolean equals(Object obj){
String name1 = this.name;
int rollno1 = this.rollno;
Student s2 = (Student)obj;
String name2 = s2.name;
int rollno2 = s2.rollno;
if(name1.equals(name2) && rollno1 == rollno2){
return true;}
else{
return false;}
}
}
来源:https://stackoverflow.com/questions/4505357/what-is-the-difference-between-operator-and-equals-with-hashcode