Java Basics: Object class surface pilot

1. Why are thread communication methods wait(), notify(), and notifyAll() defined in the Object class? Can’t be defined in the Thread class?

  • Since every object in Java has a lock called monitor, and since every object can be locked, this requires a location in the object header where the lock information is stored. The lock is at the Object level, not the thread level. Wait (), notify (), and notifyAll () are also locklevel operations whose locks belong to objects, so they are best defined in the Object class. Because the Object class is the parent of all objects, which means that all objects can be a lock Object, synchronized is a mechanism to ensure that only one Object can acquire a lock at the same time.
  • A wait () /notify () /notifyAll () method defined in class Thread has a major limitation. For example, a Thread may hold multiple locks to implement complex logic that works together. How do you make it possible for a thread to hold multiple locks? How do you know which lock the thread is waiting for? There is no way to flexibly implement such multi-lock logic, which also increases the programming difficulty.

2. Why must wait(), notify(), and notifyAll() be called in a synchronized method or synchronized block?

  • (1) in a synchronized methods or synchronized block is called wouldn’t throw Java lang. Exception IllegalMonitorStateException.
  • (2) Avoid race conditions between wait (), notify (), and notifyAll ().
  • (3) Wait () is to let the thread wait and release the lock for the thread with a deadline to use; Notify (), notifyAll () is when the thread finishes using the lock, notifying another thread that it can acquire the lock and continue executing. Notify () wakes up one thread, and notifyAll() wakes up all threads to compete.
  • (4) When a thread needs to call wait() on an object, the thread must own the lock on the object. It then releases the lock and enters the wait state until another thread calls the notify() method on the object. Similarly, when a thread needs to call the notify() method on an object, it releases the lock on the object so that other waiting threads can get the lock. Since all of these methods require the thread to hold the lock on the object and thus can only be implemented through synchronization, they can only be called in a synchronized method or synchronized block.

3.The difference between wait() and sleep() methods

  • Wait () is a member method of Object. Once an Object calls wait, the notify() and notifyAll() methods must be used to wake up the process. If a thread owns a synchronization lock on one or more objects, then after a wait() call, the thread will release all synchronization resources it holds, not limited to the object to which the wait() method was called. The wait() method is also generated by the possibility that the interrupt() method will be called by another object during the wait.
  • The sleep () method belongs to the Thread class. It means that a Thread is put into the sleep state. After a certain period of time, it automatically wakes up and enters the running state. It does not release all the object locks it holds, so it does not affect the running of other process objects. During sleep, however, it is possible for another object to interrupt(), which produces InterruptedException. If your program does not catch InterruptedException, the thread will terminate and enter the TERMINATED state. If your program catches this exception, then the program continues to execute the catch block (and possibly the finally block) and subsequent code.

4.Relationship between hashCode() and equals()

The hashCode() method retrieves the hashCode, also known as a hashCode, and returns an int. The function of this hash code is to determine the index position of the object in the hash table.

Equals () method of the role is to determine whether two objects are equal, then the Object is to pass judgment between objects in the class of memory address to determine whether the same.

  • HashCode () is mainly used to improve query efficiency and improve hash table performance. It determines the storage address of an object in a hash structure. It has no effect on linear tables.
  • Overriding equals() must override hashCode();
  • If the equals () comparison of two objects returns true, then their hashCode values must also be the same;
  • If the equals () comparison of two objects returns false, their hashCode values must be different;
  • If two objects have the same HashCode value, it does not mean that the two objects are identical. It just means that the two objects are stored in the same place in the hash storage structure.
  • If the same object is already stored in the collection during execution, information affecting the hashCode value cannot be modified, otherwise it will cause a memory leak.

== equals () == equals (

== operator:

  • When applied to a basic data type, compare two values for equality;
  • When the reference data type is used, the memory addresses of two objects are compared to determine whether they are the same object.

Equals () method:

  • When the equals() method is not overridden/overridden by the class, comparing two objects of the class via equals() is equivalent to comparing whether the two objects have the same memory address via “==”;
  • When a class overrides the equals() method, it generally compares objects based on their contents. Objects are considered equal if their contents are the same, and objects are not equal if their contents are not.
public class test1 {
   public static void main(String[] args) {
       String a = new String("ab"); // a is a reference
       String b = new String("ab"); // b is another reference, and the contents of the object are the same
       String aa = "ab"; // Put in the constant pool
       String bb = "ab"; // Search from the constant pool
       if (aa == bb) // true
             System.out.println("aa==bb");
       if (a == b) // false, not the same object
             System.out.println("a==b");
       if (a.equals(b)) // true
             System.out.println("aEQb");
       if (42= =42.0) { // true
             System.out.println("true"); }}}Copy the code

Description:

  • The equals method in String is overridden because the equals method of object compares the memory address of the object, while the equals method of String compares the value of the object.
  • When an object of type String is created, the virtual machine looks in the constant pool for an existing object with the same value as the one being created, and if so, assigns it to the current reference. If not, create a new String in the constant pool.

6.Why would you normally override hashCode() when overwriting equals()?

-string source code:

public boolean equals(Object anObject) {
    if (this == anObject) {
        return true;
    }
    if (anObject instanceof String) {
        String anotherString = (String)anObject;
        int n = count;
        if (n == anotherString.count) {
        char v1[] = value;
        char v2[] = anotherString.value;
        int i = offset;
        int j = anotherString.offset;
        while(n-- ! =0) {
            if(v1[i++] ! = v2[j++])return false;
        }
        return true; }}return false;
    }


public int hashCode() {
    int h = hash;
    if (h == 0) {
        int off = offset;
        char val[] = value;
        int len = count;

            for (int i = 0; i < len; i++) {
                h = 31*h + val[off++];
            }
            hash = h;
        }
        return h;
    }
Copy the code

The equals() method provided by the Object class defaults to ==, which means that only two objects are equal if they are the same. In real business, we usually need to think of two different objects as equal if their contents are the same. In this case, the default implementation of the equals() method in the Object class has no practical value, so it is usually overridden.

Because hashCode() is linked to equals() :

  • In Java, a Set interface represents an unordered, unrepeatable collection of elements, and a HashSet is a typical implementation of a Set interface.
  • When an element is added to a HashSet, it needs to determine whether the element is already included in the set to avoid duplicate storage. Due to the frequency of this judgment, efficiency should not be achieved by traversing the set to compare each element. In fact, a HashSet solves this judgment problem by getting the hash code of the object and calling the object’s equals() method.
  • A HashSet first calls the object’s hashCode() method to get its hashCode and uses the hashCode to determine where the object resides in the collection. Assuming that an object already exists at this location, the HashSet calls equals() to compare the two objects. If it is equal, the object is repeated, and the newly added object is not saved. If the difference means that the objects are not the same, but the locations where they are stored collide, the HashSet will use a chain structure to store multiple objects in the same location, that is, the new object is linked to the original object. Later, when a new object is mapped to the same location, an equals() comparison is performed against all objects in that location, and if none are equal, it is chained to the last object.
  • To ensure that the same object has the same hashCode value under equals, when equals() overwrites it, hashCode() is usually overridden so that the two methods always meet the convention.