夯實Java基礎(五)——==與equals()

一、前言

咱們在學習Java的時候,看到==、equals()就認爲比較簡單,隨便看了一眼就過了,其實你並無深刻去了解兩者的區別。這個問題在面試的時候出現的頻率比較高,並且據統計有85%的人義正詞嚴的答錯。因此理解==與equals()的區別頗有必要。java

二、==運算符

==可使用在基本數據類型變量和引用數據類型變量中。面試

一、若是比較的是基本數據類型變量:比較兩個變量的數值是否相等(數據類型不必定要相等,只看值,由於會類型自動提高!);數組

二、若是比較的是引用數據類型變量:比較兩個對象的地址值是否相等。ide

下面看一下案例:學習

public class Test {
    public static void main(String[] args) {
        int a=10;
        int b=10;
        double c=10.00;
        System.out.println(a==b);//true
        System.out.println(a==c);//true

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

        String str3=new String("123");
        String str4=new String("123");
        System.out.println(str3==str4);//false
    }
}

結果爲:true、true、true、false。前面兩個爲true的結果很是容易理解,可是第三個爲true,第四個爲false,而它們都是String引用類型,爲何不同呢?測試

分析緣由:this

對於8種基本數據類型(byte,short,char,int,float,double,long,boolean)的值而言,它們都是存儲在常量池中,而str一、str2的字符串 "123" 也一樣在常量池中,而一個常量只會對應一個地址,所以不論是再多的數據都只會存儲一個地址,因此全部他們的引用都是指向的同一塊地址,所以基本數據類型和String常量是能夠直接經過==來直接比較的。spa

而str三、str4分別在堆內存中建立的兩個對象,地址值天然就不相同了。code

三、equals()方法

equals()是一個方法,不是數據類型,因此他只適用於引用數據類型。對象

該方法主要用於比較兩個對象的內容是否相等。其實這樣的說法是不許確的。首先咱們來看看在Object類中定義的equals方法:

能夠看到,在Object類型的equals方法是直接經過==來比較的,和==是沒有任何區別的。

那麼爲何又要說equlas和==的區別呢?是由於全部的類都直接或間接地繼承自java.lang.Object類,所以咱們能夠經過重寫equals方法來實現咱們本身想要的比較方法。

咱們建立一個Person類來測試,先不重寫父類的equals()方法:

public class Test {
    public static void main(String[] args) {
        Person person1=new Person("菜徐坤",21);
        Person person2=new Person("菜徐坤",21);
        System.out.println(person1.equals(person2));
    }
}

class Person{
    private String name;
    private int age;

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

毫無疑問,輸出的結果確定是false,由於沒有重寫父類的equals()方法,從而調用了父類的,而父類的equals()方法是用==判斷的。

而後咱們重寫父類的equals()方法:

public class Test {
    public static void main(String[] args) {
        Person person1=new Person("菜徐坤",21);
        Person person2=new Person("菜徐坤",21);
        System.out.println(person1.equals(person2));
    }
}

class Person{
    private String name;
    private int age;

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

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

        Person person = (Person) o;

        if (age != person.age) return false;
        return name != null ? name.equals(person.name) : person.name == null;
    }
}

重寫以後輸出就是true了,由於比較的對象的內容。

實際上,像String、Date、Math、File、包裝類等大部分類都重寫了Object的equals()方法。重寫之後,就不是比較兩個對象的地址值是否相同了,而是比較兩個對象裏面的內容是否相等。

下面咱們來看一下String類重寫的equals()方法:

* @see  #compareTo(String)
     * @see  #equalsIgnoreCase(String)
     */
    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;
    }

能夠看到重寫的方法內用char[] 數組進行一個一個的比較,並非用==進行比較,。

咱們在重寫equals()方法時必需要遵循以下幾個規則:

  1. 自反性:x.equals(x)必須返回是true。
  2. 對稱性:若是x.equals(y),返回時true,那麼y.equals(x)也一定返回爲true。
  3. 傳遞性:若是x.equals(y)返回的true,並且y.equals(z)返回是true,那麼z.equals(x)返回的也是true。
  4. 一致性:若是x.equals(y)返回是true,只要x和y的內容一直不變,無論重複x.equals(y)多少次,返回都是true
  5. 任何狀況下,x.equals(null),永遠返回是false,x.equals(與x是不一樣類型的對象),也永遠返回是false。

對於上面幾個規則,咱們在使用的過程當中最好遵照,避免出現意想不到的錯誤。

四、小結

一、==比較的數值是否相等和對象地址是否相等。

二、equals()方法比較的對象內容是否相等(前提是重寫了父類的方法)。

三、通常除了自定義的類除外,大部分可以使用的類都重寫了equals()方法。

相關文章
相關標籤/搜索