Java based Object

Method summary

public final native Class<?> getClass() //Gets the runtime class of the object

public native int hashCode()        //Gets the hash value of the object

public boolean equals(Object obj)   //Compare two objects for equality

protected native Object clone()     //Creates and returns a copy of an object

public String toString()    //Returns the string representation of the object. 

public final native void notify()   //Wake up a thread waiting on the object

public final native void notifyAll()    //Wake up all threads waiting on the object

public final void wait()    //Put the current thread into a waiting state. Until another thread calls the notify() method or notifyAll() method of this object. 

public final native void wait(long timeout)  //Keep the current thread in a waiting (blocking) state until other threads call the notify() method or notifyAll() method of this object, or exceed the timeout set by the parameter. 

public final void wait(long timeout, int nanos)  //Similar to the wait(long timeout) method, there is an additional nanos parameter, which represents the additional time (in nanoseconds, the range is 0-999999). So it takes a nanosecond timeout.. 

protected void finalize()   //This method is called by the object's garbage collector when the GC (garbage collector) determines that there are no more references to the object.

equals()

equivalence relation

  • Reflexivity
x.equals(x) //true
  • Symmetry
 x.equals(y) == y.equals(x) //true
  • Transitivity
x.equals(y) //true
y.equals(z) //true
x.equals(z) //true
  • uniformity
    The equals() method is called multiple times, and the result remains unchanged
x.equals(y) == x.equals(y); // true
  • Comparison with null
    Calling x.equals(null) on any object x that is not null will result in false
x.equals(null); // false;

Equivalence and equality

  • For basic types, = = determines whether two values are equal. Basic types have no equals() method
  • For reference types, = = determines whether the references of two values are equal, while the equals() method determines whether the referenced objects are equal
Integer x = new Integer(1);
Integer y = new Integer(1);
System.out.println(x.equals(y)); // true
System.out.println(x == y);      // false

realization

  • Check whether it is a reference to the same object. If so, return true directly;
  • Check whether it is the same type. If not, return false directly;
  • Transform the Object object;
  • Determine whether each key field is equal.
public class EqualExample {

    private int x;
    private int y;
    private int z;

    public EqualExample(int x, int y, int z) {
        this.x = x;
        this.y = y;
        this.z = z;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        EqualExample that = (EqualExample) o;

        if (x != that.x) return false;
        if (y != that.y) return false;
        return z == that.z;
    }
}

hashCode()

hashCode is used to obtain the hash value of the object, indicating the position in the hash table.

The equals() method determines whether two objects are equivalent. The hash values of two equivalent objects must be equal, while the hash values of two objects with equal hash values are not necessarily equivalent, because the calculated hash value is random.

When overriding the equals() method of object, you should always override the hashCode() method to ensure that the hash values of two equivalent objects are also equal

Both the String and ArrayList classes override the equals() method of Object and rewrite the hashCode() method

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
    
    public boolean equals(Object anObject) {
        if (this == anObject) {
            return true;
        }
        if (anObject instanceof String) {
            String anotherString = (String)anObject;
            int n = value.length;
            if (n == anotherString.value.length) {
                char v1[] = value;
                char v2[] = anotherString.value;
                int i = 0;
                while (n-- != 0) {
                    if (v1[i] != v2[i])
                        return false;
                    i++;
                }
                return true;
            }
        }
        return false;
    }   
    
    public int hashCode() {
        int h = hash;
        if (h == 0 && value.length > 0) {
            char val[] = value;
    
            for (int i = 0; i < value.length; i++) {
                h = 31 * h + val[i];
            }
            hash = h;
        }
        return h;
    }    
}

When rewriting the hashCode method, you need to use the prime 31 as the multiplier, because 31 can be optimized by the JVM

  • Shift left < <: discard the highest bit on the left and complete 0 on the right (move the data on the left * 2 to the power).
  • Shift right > >: move the data on the left of > > to the power of / 2.
  • Move right without sign > > >: no matter the highest order is 0 or 1, fill 0 on the left.

Therefore: 31 * I = (I < < 5) - I (left 31 * 2 = 62, right 2 * 2 ^ 5-2 = 62) are equal on both sides, and the JVM can calculate efficiently

toString

The toString() method is used to return the string representation of the object. Default return format: hexadecimal string of object class name + @ + hashCode.

   public static void main(String[] args) {
       A a = new A();
       System.out.println(a.toString());    //client.A@b4c966a
   }

clone()

1. cloneable

clone() is the protected method of Object. It is not public. If a class does not explicitly override clone(), other classes cannot directly call the clone() method of the class instance.

public class A {

   public static void main(String[] args) {
       A a = new A();
       a.clone();   //Unhandled exception: java.lang.CloneNotSupportedException
   }
}

To rewrite the clone() method, you must implement clonable, because the clonable interface stipulates that if a class does not implement the clonable interface and calls the clone() method, it will throw Java lang.CloneNotSupportedException

public class A implements Cloneable {

    private int a;
    private int b;

    @Override
    public Object clone() throws CloneNotSupportedException {
        return super.clone();
    }

    public static void main(String[] args) throws CloneNotSupportedException {
        A a = new A();
        a.clone();
    }
}

2. Light copy

The reference type of the copy object and the original object refer to the same object.

public class A implements Cloneable {

    private int arr;

    public int getArr() {
        return arr;
    }

    public void setArr(int arr) {
        this.arr = arr;
    }

    @Override
    public A clone() throws CloneNotSupportedException {
        return (A) super.clone();
    }

    public static void main(String[] args) throws CloneNotSupportedException {
        A a = new A();
        a.setArr(123);
        A a1 = null;
        a1 = a.clone();
        System.out.println(a1.getArr()); //123
    }
}

3. Deep copy

The reference types of the copied object and the original object refer to different objects.

public class A implements Cloneable {

    private int arr;

    public int getArr() {
        return arr;
    }

    public void setArr(int arr) {
        this.arr = arr;
    }

    @Override
    public A clone() throws CloneNotSupportedException {
        A result = (A) super.clone();
        result.arr = this.arr;
        return result;
    }

    public static void main(String[] args) throws CloneNotSupportedException {
        A a = new A();
        a.setArr(123);
        A a1 = null;
        a1 = a.clone();
        System.out.println(a1.getArr()); //123
    }
}

4. Alternative to clone ()

Using the clone() method to copy an object is complex and risky. It will throw exceptions and require type conversion. As mentioned in the Effective Java book, it's better not to use clone(). You can use copy constructor or copy factory to copy an object.

public class A {

    private int arr;

    public int getArr() {
        return arr;
    }

    public void setArr(int arr) {
        this.arr = arr;
    }

    public A() {
    }

    public A(A a) {
        this.arr = a.arr;
    }

    public static void main(String[] args){
        A a = new A();
        a.setArr(123);
        A a1 = new A(a);
        System.out.println(a1.getArr());    //123
    }
}

Tags: Java

Posted by cidesign on Wed, 04 May 2022 13:09:58 +0300