Common objects (hashCode, getClass, toString, equals, clone methods in object (class))

Keywords: Java Back-end

1. Overview of API and Object class

1.API(Application Programming Interface) 
     Application programming interface
2.Java API
     It is the classes provided by Java for us to use. These classes encapsulate the underlying implementation,
     We don't need to care about how these classes are implemented, we just need to learn how to use these classes.
3.Object class overview
     Root class of class hierarchy
     All classes inherit directly or indirectly from this class
4. Construction method
    public Object()
     Recall why object-oriented says:
     The constructor of a subclass accesses the parameterless constructor of the parent class by default

2. hashCode() method of object class

 public int hashCode()
         a: Returns the hash code value of the object. By default, this method calculates based on the address of the object.
         b: hashCode() of different objects will not be the same in general.
             However, the hashCode() value of the same object must be the same.
         c: It is not the actual address value of the object, but can be understood as the logical address value.     

//import java.lang.Object;  // For classes under java.lang package, import statements can be omitted without writing
public class MyTest{
    public static void main(String[] args) {
        //java.lang
        //Object is the top-level parent class of all classes. All classes are directly or indirectly inherited from him
        Object obj= new Object();
        System.out.println(obj);
        //a: Returns the hash code value of the object. By default, this method calculates based on the address of the object.
        int i = obj.hashCode();
        System.out.println(i);
        Object obj2 = new Object();
        System.out.println(obj2);
        int i1 = obj2.hashCode();
        System.out.println(i1);
        //The hash code values of different objects are different.

    }
}

3. getClass() method of object class

 public final Class getClass()
         a: Returns the runtime class of this Object.
         b: You can obtain the full name of the real Class of the object through a method in the Class.     
        public String getName()

public class MyTest2 {
    public static void main(String[] args) {
        //Object.java -- compile -- object. Class (bytecode file) -- load > object. Class,
        // The virtual machine creates the object of the bytecode file. Bytecode types are represented by classes types
        Object obj = new Object();
        //Gets the bytecode file object of this class.
        Class<?> aClass = obj.getClass();
        Object obj2 = new Object();
        Class<?> aClass1 = obj2.getClass();
        System.out.println(obj==obj2); //false

        Object object3 = new Object();
        Class<?> aClass2 = object3.getClass();


        System.out.println(aClass==aClass1); //true



        System.out.println(aClass1 == aClass2);

    }
}

 

4. toString() method of object class

1. Case demonstration
    public String toString()
     a: Returns a string representation of the object.
         Source code:
             public String toString() {
                        return getClass().getName() + "@" + Integer.toHexString(hashCode());
                }
     b: Its value is equal to:  
        getClass().getName() + '@' + Integer.toHexString(hashCode()) 
     c: Since the default data is meaningless to us, it is generally recommended to rewrite this method.
       How to rewrite it is generally to return all the member variables of the class
2. Final version
     Automatic generation
3. Directly output the corresponding name, that is, call the toString() method of the object

Students:

public class Student extends Object{
}

Test class:

public class MyTest {
    public static void main(String[] args) {
        Object obj = new Object();
        //The address value of the toString() method or object, which is returned as a string.
        String s = obj.toString();
        System.out.println(s);
        //When you print the object name, you actually call the toString() method, but we often omit it.
        System.out.println(obj);

        Student student = new Student();
        System.out.println(student.toString());

        int i = student.hashCode();
        System.out.println(i);

        Class<? extends Student> aClass = student.getClass();
        System.out.println(aClass);

    }
}

Override the toString method in the Student class:

Student class:

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 void show() {
        System.out.println(name + "====" + age);
    }
/*
    @Override
    public String toString() {
        return "Name: "+ name +" age: "+ age;
    }
    */

    //Generally, when overriding the toString() method, our custom classes like to output the value of member variables

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

Test class:

public class MyTest {
    public static void main(String[] args) {
        Student student = new Student();
        student.setName("zhangsan");
        student.setAge(23);
       // String name = student.getName();
       // int age = student.getAge();
      //  System.out.println(name+"===="+age);

        student.show();

        /*
        public String toString () {
            return this.getClass().getName() + "@" + Integer.toHexString(hashCode());
        }

         */
           /*
           *  Object The default implementation of the toString() method in the class is the address value of the print object,
           * However, some subclasses feel that the address value of the printed object is of little significance. They want to print what they think is meaningful
           * For example, for our custom class Student, he wants to print the value of the member variable, but the address value of the object. The Student subclass should override the parent toString() method to print the value of the member variable.
           *
           * */
         System.out.println(student.toString());
    }
}

If you print an Object name in the future without outputting the address value, it means that this class overrides the toString() of the parent Object class;

For example, Scanner rewrites the toString method:

import java.util.Scanner;
public class MyTest2 {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        //If you print an Object name in the future without outputting the address value, it means that this class overrides the toString() of the parent Object class;
        System.out.println(scanner);
    }
}

5. equals() method of object class

1. Case demonstration
     a: Indicates whether some other object is "equal" to this object.  
         Source code:     
                public boolean equals(Object obj) {
                        return (this == obj);
                }
     b: By default, the comparison is whether the references of objects are the same.
     c: Since the reference of the comparison object is meaningless, it is generally recommended to override this method. It is generally used to compare whether the values of member variables are equal
     d: The difference between = = and equals() (interview question)

Before overriding the equals method, compare whether the address values of two objects are equal:
Student class:

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 boolean equals(Object obj){
        return this==obj;
    }
}

Test class:

public class MyTest {
    public static void main(String[] args) {
        Object obj = new Object();
        Object obj2= new Object();
        //==No. can judge whether the address values of two objects are the same
        System.out.println(obj==obj2);

        /*
        *   public boolean equals(Object obj) {
                 return (this == obj);
            }
        *
        * */
        boolean b = obj.equals(obj2);
        System.out.println(b);


        Student student = new Student();
        Student student1 = new Student();
        System.out.println(student==student1);

        student.equals(student1);
    }
}

After overriding the equals method, compare whether the member variables of two objects are equal:
Student class:

public class Student {
    private String name;
    private int age;

    public Student() {
    }

    public Student(String name, int age) {
        this.name = name;
        this.age = 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 void show() {
        System.out.println(name + "====" + age);
    }
    //Override the equals method: compare whether the values of the member variables of two objects are the same.
    // boolean b = s1.equals(s2);

    /*
     * The robustness of the code. Consider it carefully. In terms of performance
     *
     * */
    @Override
    public boolean equals(Object obj) {  // Object obj=s2  Student
        //Make non null judgment on the passed in parameters
        if(obj==null){
            return false;
        }
        //In terms of performance
        if(this==obj){
            return true;
        }
        //Access member variables in polymorphic form. See the left for compilation and the left for operation.
        //Downward transformation, we have to judge instanceof
        // instanceof determines whether a reference or object is of this type
        if (!(obj instanceof Student)) { //Judge whether obj is a Student reference
            return false;
        }
        //Downward transformation
        Student s2= (Student) obj;
        // 23 = = 24 & & "Li Si" = = "Li Si"
        // String reference type = = sign comparison two objects compare the address value. What we mean now is to compare whether the literal contents of the two strings are the same
        //We want to compare two strings, whether the literal content is the same, and call the equals() method in the string to compare
        return this.age == s2.age && this.name.equals(s2.name);
    }

}

Test class:

public class MyTest2 {
    public static void main(String[] args) {
        Student s1 = new Student("Zhang San", 23);
        Student s2 = new Student("Zhang San", 23);
        /*
        * Object The default implementation of the equals() method in the class is to compare the address values of two objects to see if they are the same
        * But now we have to compare like this: we think that if the values of the member variables of two objects are the same, I think the two objects are equal.
        * That is, instead of comparing the address values of the two objects, we compare whether the values of the member variables of the two objects are the same.
        * Then we have to override the equals() method to compare in our own way.
        *
        * */

        Dog dog = new Dog();
        s2=null;
        boolean b =s1.equals(null);
        System.out.println(b);
    }
}

Take dogs for example:

public class Dog {
}

6. Code optimization of equals() method of object class

1. Case demonstration
     Code optimization of equals() method of Object class
         a: Improve efficiency
         b: Improve robustness (instanceof)     
2. Final version
     Automatic generation

Auto generate equals method:

import java.util.Objects;
public class Student {
    private String name;
    private int age;

    public Student() {
    }

    public Student(String name, int age) {
        this.name = name;
        this.age = 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;
    }

    @Override
    public boolean equals(Object o) {
        //If you compare yourself with yourself, go straight to true
        if (this == o) {
            return true;
        }
        // Judge whether a reference or object is a reference or object of this type
        //s1.getClass()==s2.getClass();
        // instanceof determines whether a reference or object is of this type
        if (o==null||this.getClass() != o.getClass()) {
            return false;
        }
        //Downward transformation
        Student student = (Student) o;
       /*
       *      public static boolean equals(Object a, Object b) {
                        return (a == b) || (a != null && a.equals(b));
                }
       *
       * */
        //return this.age == s2.age && this.name.equals(s2.name);
        return this.age == student.age && Objects.equals(name, student.name);
    }
}

7. clone() method of object class

The permission modifier of clone() is protected. When using, let the class override the method, and change the permission modifier of the method to shallow cloning of public objects: shallow cloning and deep cloning

Details for shallow cloning of objects:

  1. If an object needs to call clone's method cloning, the class to which the object belongs must implement the clonable interface.

  2. Cloneable interface is just an identification interface without any methods.

  3. Shallow cloning of an object is when cloning an object. If the object of another class is maintained in the cloned object, it is only the address of another object to be cloned, and another object is not cloned.

  4. A shallow clone of an object will not call the constructor.

Deep cloning of objects (to be discussed later): the object is written to a file using ObjectOutputStream and then read back with ObjectInputStream

Normal clone:

public class MyTest{
    public static void main(String[] args) throws CloneNotSupportedException {
       // protected Object clone() creates and returns a copy of this object.
        //1. The permission modifier of clone () is protected. When used, let the class rewrite the method, the rewriting logic continues to call the cloning logic of the parent class, and change the permission modifier of the method to public
        //2. If an object needs to call clone method cloning, the class to which the object belongs must implement clonable interface.
        //3. Clonable interface is just an identification interface without any method.

        Dog dog = new Dog("Xiaobai", 2);
        Dog dog2 = (Dog) dog.clone();
        System.out.println(dog);
        System.out.println(dog2.toString());
    }
}
// There are no abstract methods in the clonable interface. This interface is just a tag interface. It marks the class to tell the JVM to perform cloning
class Dog implements Cloneable{
    String name;
    int age;
    public Dog() {
    }

    public Dog(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public Object clone() throws CloneNotSupportedException {
        return super.clone(); //Continue to call the clone of the parent class Object
    }

    @Override
    public String toString() {
        return "Dog{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

Shallow clone:  

public class MyTest {
    public static void main(String[] args) throws CloneNotSupportedException {

        /*
        *  3. Shallow cloning of an object is when cloning an object. If the cloned object maintains an object of another class,
        * At this time, only the address of another object is cloned, and another object is not cloned.
	        4. A shallow clone of an object will not call the constructor.
        *
        * */
        DogFood dogFood = new DogFood("golden gong");
        Dog dog = new Dog("Xiaobai", 2, dogFood);
        dog.dogFood.foodName="Wang Zhongwang";

        //clone
        Dog dog2 = (Dog) dog.clone();
        dog2.dogFood.foodName="Corn sausage";

        System.out.println(dog.dogFood.foodName); // Corn sausage

        System.out.println(dog2.dogFood.foodName); // Corn sausage

    }
}

class Dog implements Cloneable {
    String name;
    int age;
    //Member variable, DogFood type
    DogFood  dogFood;
    public Dog() {

    }
    public Dog(String name, int age, DogFood dogFood) {
        System.out.println("Constructor called");
        this.name = name;
        this.age = age;
        this.dogFood = dogFood;
    }

    @Override
    public Object clone() throws CloneNotSupportedException {
        return super.clone(); //Continue to call the clone of the parent class Object
    }
}

class DogFood {
    String foodName="Shuanghui";
    public DogFood() {
    }
    public DogFood(String foodName) {
        this.foodName = foodName;
    }
}

Posted by shivangp on Sun, 07 Nov 2021 17:43:43 -0800