What is the difference between the operator = = and the equals() method?
- ==Operator is used to compare whether the addresses of two objects are equal
- equals() is used to compare whether the contents of two objects are equal
// String object comparison String alita=new String("Little Laurie"); String luolita=new String("Little Laurie"); System.out.println(alita.equals(luolita)); // true System.out.println(alita == luolita); // false
. The result output by equals() is true, while the result output by the "= =" operator is false
The former requires equal content, while the latter requires the same object.
All classes in Java inherit the superclass Object by default. This class has a superclass named Object Method of equals().
Object source code
public boolean equals(Object obj) { return (this == obj); }
Object class The equals() method uses the "= =" operator by default for comparison.
If the subclass does not override the method, the "= =" operator and The equals() method does exactly the same thing -- comparing the memory addresses of two objects.
equals() source code
public boolean equals(Object anObject) { if (this == anObject) { return true; } if (anObject instanceof String) { String aString = (String)anObject; if (coder() == aString.coder()) { return isLatin1() ? StringLatin1.equals(value, aString.value) : StringUTF16.equals(value, aString.value); } } return false; }
First, if the of two string objects can be "= =", it will directly return true, because in this case, the string contents must be equal. Otherwise, compare according to the character code, which is divided into UTF16 and Latin1. The difference is not very big. Take Latin1 for example.
public static boolean equals(byte[] value, byte[] other) { if (value.length == other.length) { for (int i = 0; i < value.length; i++) { if (value[i] != other[i]) { return false; } } return true; } return false; }
My JDK version is Java 11, That is, the latest version of LTS (long-term support). In this version, the String class is implemented using byte arrays. Therefore, when comparing the contents of two strings, you can first compare whether the length of byte arrays is equal. If they are not equal, false will be returned directly; otherwise, the byte arrays of two strings will be traversed, and false will be returned as long as one byte is not equal.
Question 1:
new String("Little Laurie").equals("Little Laurie")
. equals() compares whether the contents of two string objects are equal, so the result is true.
Question 2:
new String("Little Laurie") == "Little Laurie"
==The left side of the operator is the object created in the heap, and the right side is the object in the string constant pool. Although the contents are the same, the memory addresses are different, so false is returned.
Question 3:
new String("Little Laurie") == new String("Little Laurie")
The new object must have a completely different memory address, so false is returned.
Question 4:
"Little Laurie" == "Little Laurie"
There will only be one object with the same content in the string constant pool, so it returns true
Question 5:
"Little Laurie" == "Small" + "lolita"
Since both 'little' and 'Laurie' are in the string constant pool, the compiler automatically optimizes the '+' operator to "little Laurie" when encountering it, so it returns true.
Question 6:
new String("Little Laurie").intern() == "Little Laurie"
When new String("little Laurie") is executed, it will first create objects in the string constant pool, and then create objects in the heap; When executing the intern() method, it is found that the object "little Lori" already exists in the string constant pool, so it directly returns the object reference in the string constant pool. Compared with the "little Lori" in the string constant pool, it will certainly return true
If you want to compare the contents of two string objects, except The equals() method, and there are two other alternatives.
1)Objects.equals()
Objects. The advantage of the static method equals () is that it does not need to be null before calling.
public static boolean equals(Object a, Object b) { return (a == b) || (a != null && a.equals(b)); }
If you directly use a.equals(b), you need to empty a before calling, otherwise you may throw a null pointer Java lang.NullPointerException.
Objects.equals("Little Laurie", new String("Small" + "lolita")) // --> true Objects.equals(null, new String("Small" + "lolita")); // --> false Objects.equals(null, null) // --> true String a = null; a.equals(new String("Small" + "lolita")); // throw exception
2) String class contentEquals()
. The advantage of contentEquals() is that it can compare strings with any character sequence (StringBuffer, StringBuilder, String, CharSequence).
public boolean contentEquals(CharSequence cs) { // Argument is a StringBuffer, StringBuilder if (cs instanceof AbstractStringBuilder) { if (cs instanceof StringBuffer) { synchronized(cs) { return nonSyncContentEquals((AbstractStringBuilder)cs); } } else { return nonSyncContentEquals((AbstractStringBuilder)cs); } } // Argument is a String if (cs instanceof String) { return equals(cs); } // Argument is a generic CharSequence int n = cs.length(); if (n != length()) { return false; } byte[] val = this.value; if (isLatin1()) { for (int i = 0; i < n; i++) { if ((val[i] & 0xff) != cs.charAt(i)) { return false; } } } else { if (!StringUTF16.contentEquals(val, cs, n)) { return false; } } return true; }
It can be seen from the source code that if cs is StringBuffer, this method will also synchronize, which is very intelligent; If it is a String, the equals() method is actually called.
Comparison of custom objects
The String compared above is the system's own. Let's see if you can use equals if you define your own class?
package com.study; import java.util.Objects; /** * @Description TODO * @Classname Person * @Date 2021/8/22 14:45 * @Created by Tossing Xiaofei */ public class Person { private String name; // name private int age; // Age // Nonparametric structure public Person() { } // Parametric structure public Person(String name, int age) { this.name = name; this.age = age; } // Get method and set method are used to get and set the value of member variables 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; } // toString method for printing @Override public String toString() { return "Person{" + "name='" + name + '\'' + ", age=" + age + '}'; } } // Comparison of custom objects Person p1 = new Person("distinguished", 22); Person p2 = new Person("distinguished", 22); System.out.println(p1 == p2); // faslse System.out.println(p1.equals(p2)); //false
What's going on?
How to use equals comparison or false?
ctrl + left click to find
public boolean equals(Object obj) { return (this == obj); }
When it is the same object, return true; Not an object, return false.
We found that it is still a comparative address. What should we do?
We need to override the equals() method to compare the contents of the object
The overridden equals() method is as follows:
@Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Person person = (Person) o; return age == person.age && Objects.equals(name, person.name); }
First, judge whether it is the same object
Second, judge whether the incoming object is empty and whether the class names are equal
Third, judge whether the attribute values are equal
There is also a hashCode() method to compare whether the hash value of the object is the same
System.out.println(p1.hashCode()); System.out.println(p2.hashCode());
It is found that the contents of the two objects are the same and the addresses are different.
What if we want to compare the hashCode value of the content?
We can also override the hashCode() method to compare the hash value of the object content
@Override public int hashCode() { return Objects.hash(name, age); }
Therefore, when comparing custom objects, you need to override the equals() and hashCode() methods