The Object class is the parent class of all classes. Any class inherits Object by default. It is located in the java.lang package. What methods does the Object class mainly implement?
toString method
The toString method can convert any object into a string and return it. The generation algorithm of the return value is: getClass().getName() + '@' + Integer.toHexString(hashCode()). However, subclasses generally override this method.
equals method
The equals method in the Object class is used to compare the virtual addresses of two references. If and only if two references are physically the same Object, the return value is true, otherwise false will be returned. However, subclasses generally override this method.
hashCode method
Gets the hash code value of the object, in hexadecimal.
clone method
Protect the method and realize the shallow replication of objects. This method can be called only when the clonable interface is implemented. Otherwise, a clonnotsupportedexception exception will be thrown.
getClass method
final method to get the class object of the class.
wait method
Causes the thread to enter a wait state until it is awakened by other threads through notify() or notifyAll. This method can only be invoked in the synchronization method. If the current thread is not the lock holder, the method throws an IllegalMonitorStateException. wait(long timeout) can set a timeout interval. After calling this method, the current thread enters sleep state until the following events occur:
(1) Another thread called the notify method of the object.
(2) The notifyAll method of the object was called by another thread.
(3) Another thread called interrupt to interrupt the thread.
(4) The time interval is up.
At this point, the thread can be scheduled. If it is interrupted, an InterruptedException exception will be thrown.
notify method
This method wakes up a thread waiting on the object. This method can only be called inside a synchronization method or synchronization block. If the current thread is not the lock holder, the method throws an IllegalMonitorStateException.
notifyAll method
Unblock all threads that call the wait method on this object. This method can only be called inside a synchronization method or synchronization block. If the current thread is not the lock holder, the method throws an IllegalMonitorStateException.
Why do you have to override the hashcode method to override the equals method
Because if only the equals method is rewritten and the hashcode method is not rewritten, two different instances a and b will have different hashcodes although the equals results are equal (in business logic, for example, the values of the two objects are all equal), so there will be both a and b in the hashmap. In fact, we need to save only one of them in the hashmap, Because they are equal from the perspective of business logic.
If the equals method and hashCode method are not rewritten according to your own logic at the same time, HashMap will have problems. For example, if you only rewrite the equals method but not the hashCode method, HashMap will make an error when looking for the linked list in the first step. Two objects a and B with the same value will not point to the same linked list or bucket, because you do not provide your own hashCode method, you will use the hashCode method of Object, which compares whether the two objects are consistent according to the memory address, Because a and B have different memory addresses, they will point to different linked lists. In this way, HashMap will think that B does not exist, although we expect a and B to be the same Object; On the contrary, if only the hashCode method is rewritten without overwriting the equals method, although the first step will make a and B find the same linked list, because equals is not overwritten, a.equals(b) is not true when traversing the elements of the linked list (in fact, the equals method of Object is also to compare the memory address), so HashMap considers that there is no B Object, This is also incorrect.
Code test:
The equals method and hashCode method are not overridden.
package com.redistext.equals; /** * @author: maorui * @description: TODO * @date: 2021/10/27 16:53 * @description: V1.0 */ public class Student { private String name; private int age; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public Student(String name, int age) { this.name = name; this.age = age; } }
package com.redistext.equals; import java.util.HashSet; import java.util.Set; /** * @author: maorui * @description: TODO * @date: 2021/10/27 16:54 * @description: V1.0 */ public class EqualsTest { public static void main(String[] args) { Set<Student> set = new HashSet<Student>(); Student stu1 = new Student("Zhang San",3); Student stu2 = new Student("Zhang San",3); set.add(stu1); set.add(stu2); System.out.println("stu1 == stu2 : "+(stu1 == stu2)); System.out.println("stu1.equals(stu2) : "+stu1.equals(stu2)); System.out.println("set size:"+ set.size()); } }
Test results:
The Student class does not override the equals method. When stu1 calls the equals method, it actually calls the equals method of the Object. Therefore, the Object memory address is used to judge whether the objects are equal. Because they are two new objects, the memory addresses of the objects are not equal, so stu1.equals(stu2) is false.
However, from the perspective of business logic, we believe that stu1 and stu2 have equal attribute values, and the two objects are the same, so we need to override the equals method.
package com.redistext.equals; /** * @author: maorui * @description: TODO * @date: 2021/10/27 16:53 * @description: V1.0 */ public class Student { private String name; private int age; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public Student(String name, int age) { this.name = name; this.age = age; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Student student = (Student) o; if (age != student.age) return false; return name != null ? name.equals(student.name) : student.name == null; } }
Test results:
Because the age and name attributes of the two Student objects are equal, and they are determined by overriding the equals method, stu1.equals(stu2) shown is true. However, there is another problem. We know that the set set does not save duplicate elements, but the size of the set set is still 2, indicating that stu1 and stu2 are still not used in the set set.
This has something to do with not rewriting the hashCode method. Let's rewrite the hashCode method.
package com.redistext.equals; /** * @author: maorui * @description: TODO * @date: 2021/10/27 16:53 * @description: V1.0 */ public class Student { private String name; private int age; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public Student(String name, int age) { this.name = name; this.age = age; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Student student = (Student) o; if (age != student.age) return false; return name != null ? name.equals(student.name) : student.name == null; } @Override public int hashCode() { int result = name != null ? name.hashCode() : 0; result = 31 * result + age; return result; } }
Test results:
stu1 and stu2 are equal through the equals method, and the returned hashCode values are the same, so only one object is put into the set set.
Usage scenarios of wait and notify methods
Reference documents:
Common methods in object class - swaying Xingjun - blog Garden