一文徹底弄懂雙等 “==” 和 equals 的區別,從此面試再也不會入坑了

基本數據類型:因爲基本數據類型沒有引用對象,所以 “==” 的效果就是比較值是否相同,基本數據類型沒有 equals 方法

引用數據類型:“==” 和 equals 兩者都是比較引用的對象是否相同


爲什麼我們在網上會看到說:雙等比較引用,equals比較值呢?

那是因爲equals被重寫了,重寫之後的效果就是比較值是否相等,那些例子都是用String類型之間進行比較的,String內部默認重寫了equals方法,所以纔有了以上的說法


如下是equals的源碼,可以看到equals的內部實現就是 “==”

public boolean equals(Object obj) {
    return (this == obj);
}

如下是String內部重寫equals的源碼

  • String內部重寫了equals方法,重寫後的效果就是比較兩個對象的值是否相等
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;
}

對應引用數據類型來說,可以這樣記:

  • 如果equals沒有被重寫,兩種比較是相同的

  • 如果equals被重寫了,那麼兩種比較自然不同

  • String內部默認重寫了equals方法,所以:”==“ 比較引用,equals 比較值


String測試

(”==“ 比較引用,equals 比較值)

直接定義兩個值相同的字符串進行比較

String str1 = "hello";
String str2 = "hello";
System.out.println(str1 ==  str2); // true
System.out.println(str1.equals(str2)); // true

在創建字符串的時候,會先創建一個字符串緩衝池

當創建str1時,先在字符串常量池中尋找有沒有對應“hello”的對象,如果沒有,就創建一個,然後將str1對象放入字符串常量池中,將str1的值“hello”放入常量池中

JDK1.7後:字符串常量池保存引用,常量池保存值

當創建str2時,先在字符串常量池中尋找有沒有對應“hello”的對象,發現str1對應的值和自己要創建的字符串值相同,就直接引用str1所引用的對象

所以

  • str1==str2:兩者引用的對象相同,都是“hello”;
  • str1.equals(str2)也相同:兩者的值相同

直接定義兩個值不同的字符串進行比較

String str1 = "hello";
String str2 = "hi";
System.out.println(str1 ==  str2); // false
System.out.println(str1.equals(str2)); // false
  • 兩者所引用的對象不同,所以 str1 == str2 肯定爲false
  • 兩者的值也不同,所以下面的也是false

new兩個值相同的字符串進行比較

String str1 = new String("Hello");
String str2 = new String("Hello");
System.out.println(str1 ==  str2); // false
System.out.println(str1.equals(str2)); // true

在new一個對象的時候,不會從字符串緩衝池中尋找,而是直接開闢一個新的空間來創建一個新的對象,創建的對象也不會添加到常量池中

所以

  • new了兩個對象,兩個對象的引用肯定不是同一個,雙等的比較爲false
  • 但是兩個對象的值是相同的,都是“Hello”,所以equals的比較相同爲 true

new兩個值不同的字符串進行比較

String str1 = new String("Hello");
String str2 = new String("Hi");
System.out.println(str1 ==  str2); // false
System.out.println(str1.equals(str2)); // false
  • new了兩個對象,兩個對象的引用肯定不是同一個,雙等的比較爲false
  • 兩個對象的值也是不相同的,所以equals的比較不同爲 false

直接定義一個字符串和new一個字符串進行比較(兩者值相同)

String str1 = "Hello";
String str2 = new String("Hello");
System.out.println(str1 ==  str2); // false
System.out.println(str1.equals(str2)); // true
  • 因爲str2 new了一個新對象,所以和str1的引用不是同一個,雙等的比較爲false
  • 但是兩者的值是相同的,所以equals的比較爲 true

直接定義一個字符串和new一個字符串進行比較(兩者值不同)

String str1 = "Hello";
String str2 = new String("Hi");
System.out.println(str1 ==  str2); // false
System.out.println(str1.equals(str2)); // false
  • 因爲str2 new了一個新對象,所以和str1的引用不是同一個,雙等的比較爲false
  • 兩者的值是不相同的,所以equals的比較也爲 false

其它對象測試

(”==“ 比較引用,equals 也比引用)

首先創建一個實體類

class Person {
    private int id;

    public Person(int id) {
        this.id = id;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }
}

new 兩個值相同的對象

Person person1 = new Person(12);
Person person2 = new Person(12);
System.out.println(person1 == person2); // false
System.out.println(person1.equals(person2)); // false
  • 因爲equals沒有被重寫,所以兩種比較都是一樣的,都爲false

new兩個值不同的對象

Person person1 = new Person(12);
Person person2 = new Person(25);
System.out.println(person1 == person2); // false
System.out.println(person1.equals(person2)); // false
  • 因爲equals沒有被重寫,所以兩種比較都是比較引用是否相同,和對象的值無關,所以都爲false

總結

基本數據類型:因爲基本數據類型沒有引用對象,所以 “==” 的效果就是比較值是否相同,基本數據類型沒有 equals 方法

引用數據類型:“==” 和 equals 兩者都是比較引用的對象是否相同

  • equals 方法可以被重寫
  • String內部默認重寫了 equals 方法,使其效果爲判斷兩者的值是否相等
  • 創建字符串時,會先在字符串常量池中進行查找
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章