java foundation - = = and equals methods

1.1, = = and equals methods

   there are two ways to test whether two variables are equal in Java programs: one is to use the "= =" operator, and the other is to use the equals() method. When = = is used to judge whether two variables are equal, if the two variables are basic type variables and both are numeric types (the data types are not necessarily the same), true will be returned as long as the values of the two variables are equal.
    however, for two reference type variables, the "= =" judgment will return true only when they point to the same object. "= =" cannot be used to compare two objects without parent-child relationship on type. The following program demonstrates the result of using "= =" to judge whether two types of variables are equal.

    public static void main(String[] args) {
        int it = 65;
        float fl = 65.0f;
        // true will be output
        System.out.println("65 And 65.0f Are they equal?" + (it == fl));
        char ch = 'A';
        // true will be output
        System.out.println("65 and'A'Are they equal?" + (it == ch));
        String str1 = new String("hello");
        String str2 = new String("hello");
        // false will be output
        System.out.println("str1 and str2 Are they equal?"
                + (str1 == str2));
        // true will be output
        System.out.println("str1 whether equals str2?"
                + (str1.equals(str2)));
        // Since java.lang.String does not inherit from EqualTest class,
        // Therefore, the following statement causes a compilation error
		System.out.println("hello" == new EqualTest());
    }

  run the above program and you can see that 65, 65.0f and 'A' are equal. However, for str1 and str2, because they are reference type variables, they point to two String objects created through the new keyword, so str1 and str2 variables are not equal.
   for beginners, String is also very confusing: "what is the difference between hello" directness and new String("hello")? When Java programs directly use String directness like "hello" (including String values that can be calculated at compile time), the JVM will use constant pool to manage these strings; When using new String("hello"), the JVM will first use the constant pool to manage the "hello" direct quantity, and then call the constructor of String class to create a new String object, which is saved in heap memory. In other words, new String("hello") produces a total of two String objects.
ps: constant pool is specially used to manage some data determined at compile time and saved in the compiled. class file. It includes constants in classes, methods and interfaces, as well as string constants.
   the following program demonstrates the case where the JVM uses the constant pool to manage the string direct quantity.

    public static void main(String[] args) {
        // s1 direct reference to "crazy Java" in constant pool
        String s1 = "insane Java";
        String s2 = "insane";
        String s3 = "Java";
        // The string value after s4 can be determined at compile time
        // s4 directly references "crazy Java" in the constant pool
        String s4 = "insane" + "Java";
        // The string value after s5 can be determined at compile time
        // s5 directly references "crazy Java" in the constant pool
        String s5 = "crazy" + "Crazy" + "Java";
        // The string value after s6 cannot be determined at compile time,
        // Cannot reference a string in a constant pool
        String s6 = s2 + s3;
        // Calling the constructor with new will create a new String object,
        // s7 refers to a newly created String object in heap memory
        String s7 = new String("insane Java");
        System.out.println(s1 == s4); // Output true
        System.out.println(s1 == s5); // Output true
        System.out.println(s1 == s6); // Output false
        System.out.println(s1 == s7); // Output false
    }

   the JVM constant pool ensures that there is only one direct quantity of the same string and will not produce multiple copies. The strings referenced by s1, s4 and s5 in the example can be determined at compile time, so they will all refer to the same string object in the constant pool.
    the string object created with new String() is created at run time. It is saved in the run-time memory area (i.e. heap memory) and will not be put into the constant pool.
  however, in many cases, when the program judges whether two reference variables are equal, it also hopes to have a judgment rule similar to "equal values", which does not strictly require two reference variables to point to the same object. For example, for two String variables, it may only be required that the character sequences contained in their reference String objects are the same. At this point, you can use the equals() method of the String object to judge. For example, str1.equals (str2) in the above program will return true.
The   equals() method is an instance method provided by the Object class, so all reference variables can call this method to judge whether it is equal to other reference variables. However, there is no difference between using this method to judge the equality of two objects and using the = = operator. It also requires that two reference variables point to the same Object to return true. Therefore, the equals () method provided by this Object class does not have much practical significance. If you want to adopt a custom equality standard, you can override the equals method.
ps: String has rewritten the equals() method of Object. The criteria for the equals() method of String to judge the equality of two strings is: as long as the character sequences contained in the two strings are the same, the equals() comparison will return true, otherwise it will return false.
  the following program example overrides the equals() method of the Person class.

class Person {
    private String name;
    private String idStr;

    public Person() {
    }

    public Person(String name, String idStr) {
        this.name = name;
        this.idStr = idStr;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getIdStr() {
        return idStr;
    }

    public void setIdStr(String idStr) {
        this.idStr = idStr;
    }

    // Override the equals() method to provide a custom equality standard
    public boolean equals(Object obj) {
        // If two objects are the same object
        if (this == obj)
            return true;
        // Only when obj is a Person object
        if (obj != null && obj.getClass() == Person.class) {
            Person personObj = (Person) obj;
            // If the idStr of the current object is equal to the idStr of the obj object, it can be judged that the two objects are equal
            if (this.getIdStr().equals(personObj.getIdStr())) {
                return true;
            }
        }
        return false;
    }
}

public class OverrideEqualsRight {
    public static void main(String[] args) {
        Person p1 = new Person("Sun WuKong", "12343433433");
        Person p2 = new Person("Monkey King", "12343433433");
        Person p3 = new Person("Gohan ", "99933433");
        // The idStr of p1 and p2 are equal, so the output is true
        System.out.println("p1 and p2 Are they equal?" + p1.equals(p2));
        // The idStr of p2 and p3 are not equal, so false is output
        System.out.println("p2 and p3 Are they equal?" + p2.equals(p3));
    }
}

   the above program rewrites the equals() method of the Person class and specifies the criteria for the equality of the Person object and other objects: the other object must be an instance of the Person class and the idstrs of the two Person objects are equal, so it can be judged that the two Person objects are equal. Under this judgment standard, it can be considered that as long as the ID card strings of two Person objects are equal, they can be judged to be equal.
    generally speaking, the following conditions should be met to properly override the equals() method.
Reflexivity: x.equals (x) must return true for any X.
Symmetry: for any X and y, if y.equals(x) returns true, x.equals(y) also returns true.
Transitivity: for any x, y, z, if x.equals(y) returns true and y.equals(z) returns true, then x.equals(z) must return true.
Consistency: for any X and y, if the information used for equivalence comparison in the object has not changed, the returned results should be consistent, either true or false, no matter how many times x.equals(y) is called.
     for any X that is not null, x.equals (null) must return false. The equals() provided by Object by default is only the address of the comparison Object, that is, the result of the equals() method of Object class is exactly the same as that of the = = operator. Therefore, in practical applications, it is often necessary to rewrite the equals() method. When rewriting the equals method, the equality condition is determined by the business requirements, so the implementation of the equals() method is also determined by the business requirements.

1.2. equals() and hashcode()

   equals(): used to judge whether two objects are the same. In the Object class, it determines whether they are the same by judging the memory address between objects.
   hashCode(): get hash code, also known as hash code, and return an int integer. This hash code is used to determine the index position of the object in the hash table.

   it can be seen from the comments of the Jdk source code that hashCode() will only play a role in the hash table. When the object is not used to create collections such as HashMap and HashSet, it is not necessary to rewrite the hashCode method. However, if there are operations such as using the hash set of the object, it is necessary to rewrite hashCode() and equals(). Generally, when rewriting the equals() method, it is also necessary to rewrite the hashCode() method.
  summary:

  • hashCode is mainly used to improve query efficiency and hash table performance to determine the storage address of the object in the hash structure
  • Overriding equals() must override hashCode()
  • In the hash storage structure, the standard for adding element repeatability verification is to check the hashCode value first and then judge equals()
  • The two objects equals() are equal, and hashcode() must be equal
  • The two objects hashcode() are not equal, and so must equals()
  • The two objects hashcode() are equal, but the objects are not necessarily equal. It needs to be further judged by equals().

Keywords: Java Back-end

Added by tomato on Sun, 07 Nov 2021 20:27:07 +0200