В чем разница между оператором == и equals()? (с хэш-кодом ()???)
Я изучил хэш-код более подробно и понял, что:
1. Если вы переопределяете equals(), вы также должны переопределить hashcode().
2. Чтобы определить, являются ли 2 объекта одним и тем же объектом, используйте оператор ==
Учитывая эти 2 фактора, в Java я предполагал, что когда == operator
используется для сравнения, если 2 экземпляра одинаковы или нет,
if(object1 == object2)
на самом деле делает
if(object1.hashcode() == object2.hashcode())
Но, похоже, я ошибся, выполнив тест ниже.
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;
}
}
Согласно тесту, который использует == operator
и посмотреть, если equals()
называется и не было.
Так что мой вопрос, если == operator
может использоваться для сравнения, если объект тот же или нет, какой смысл переопределять equals()
а также hashCode()
метод для сравнения? не == operator
делать работу уже?
ссылка:
Переопределение hashCode() - это достаточно хорошо?
http://mindprod.com/jgloss/hashcode.html
http://download.oracle.com/javase/1.4.2/docs/api/java/lang/Object.html
6 ответов
Оператор == определяет, указывают ли 2 ссылки на один и тот же объект.
Так
Object o1 = new Object();
Object o2 = o1;
o1 == o2; //true
o2 = new Object();
o1 == o2 // false
метод Object.equals() - это "как определить, равны ли 2 ссылки на объекты, которые не являются одним и тем же объектом?"
Если две ссылки указывают на один и тот же объект, оба
o1 == o2
o1.equals(o2)
должно быть правдой.
Но если o1 и o2 не являются одним и тем же объектом, они все равно могут быть равны логически. Для любого данного класса значение equals зависит от семантики объекта. Например, рассмотрим класс, где field1 и field2 задаются пользователем, но field3 вычисляется и имеет случайный элемент для вычисления. В этом случае может иметь смысл определять равные, чтобы зависеть только от field1 и field2, а не field3. Вот почему равенство необходимо.
==
это личность.
.equals()
равенство
.equals()
по умолчанию просто использовать ==
(как hashCode()
по умолчанию System.identityHashCode()
но вы можете переопределить их, если есть более значимый способ проверки на равенство. Как правило, это своего рода "структурное" равенство. то есть: все части this
.equal()
ко всем частям that
?
Если у вас еще нет копии; купите копию Эффективной Явы Джошуа Блохом.
Это фактический справочник для разработчиков Java, в котором содержится много информации по этой (и многим другим) темам.
==
(используется на объектах, а не на примитивных значениях) проверяет, являются ли 2 объекта фактически одним и тем же объектом; он сравнивает, действительно ли указатели указывают на одну и ту же область памяти.
.equals()
определяется самим объектом.
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()
это уловка оптимизации (во всяком случае, в большинстве случаев). Много кода в стандартных библиотеках предполагает, что если o1.equals(o2)==true
затем o1.hashCode()==o2.hashCode()
и что если o1.hashCode()!=o2.hashCode()
затем o1.equals(o2)==false
для того, чтобы работать быстрее.
Наиболее очевидным примером такой оптимизации является класс HashMap. Это делает поиск объектов с использованием ключа действительно быстрым, но плохо работает, если hashCode и equals не работают должным образом для ключевых элементов. Фактически, это одна из причин того, что класс String является неизменяемым: если вы смогли изменить String (и, следовательно, изменить его hashCode), в то время как String был ключом в HashMap, то вы никогда бы не смогли найти его, так как вы в конечном итоге искать его в неправильном месте!
Другие ответы рекомендуют " Эффективная Java " Джошуа Блоха. Если вы задаете такие вопросы, то сейчас самое подходящее время в вашей карьере, чтобы купить книгу и прочитать ее от корки до корки. Это также будет стоить перечитать через год или два, когда вы забудете некоторые из них, и многое из этого будет иметь смысл...
На большинство уже ответили, так что вот еще один поучительный пример:
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
==
оператор -> проверяет погоду 2 ссылки указывают на один и тот же объект или нет. Если то же самое, вернуть true, иначе false.
equals( )
-> проверяет как ссылку, так и объект состояния. Состояние слуха означает данные объекта. В этом случае любой верен, он возвращает истину. В противном случае ложь. Но мы должны переопределить equals( )
в нашем определяемом пользователем объекте и пишем соответствующий код.
Hashcode( )
->hashCode объекта просто представляет случайное число, которое может использоваться JVM при сохранении / добавлении объектов в Hashsets, Hashtables или Hashmap.
Пример 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;}
}
}