Java基礎-equals方法

來源:互聯網
上載者:User

標籤:其他   獲得   沒有   end   rri   特性   bool   etag   內容   

    Object類中的equals方是用來判斷一個對象等於另一個對象,至於這個等於的條件需要,比如說,String類的equals相等的條件就是字串的內容必須相同,equals方法返回的值才為true。所以在我們在自己定義的類中,equals的重寫是常見的!這裡主要展示equals的特性和equals的正確寫法,至於equals方法具體的含義這裡不介紹!

1. 舉一個例子

    在這介紹其他的,我們先來看看正確的寫法

public class Animal {    private String name = null;    public Animal(String name) {        this.name = name;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    @Override    public boolean equals(Object obj) {        if(this == obj) {            return true;        }        if(obj == null) {            return false;        }        if(this.getClass() != obj.getClass()) {            return false;        }        Animal animal = (Animal) obj;        //return this.name.equals(animal.name);        //這個方法只在JDK7及其以後才有的        //這個方法能夠保證兩個name其中只有一個為null的話,返回的false        //如果兩個都為null的話,返回的是true        //如果兩個都不為null的話,具體看情況        return Objects.equals(this.name, animal.name);    }}

    從上面的代碼中我們看到是,Animal類的equals方法判斷的相等條件是name是否為相同。說實話,判斷的條件非常的簡單,但是我們的代碼寫的非常複雜。可能有人會這樣寫的:

    public boolean equals(Object obj) {        if(! (obj instanceof Animal)) {            return false;        }        Animal animal = (Animal) obj;        return this.name.equals(animal.name);    }

    實際上,上面的代碼是有很大的問題,至於有什麼問題,待會再說!這裡我們來解釋一下正確equals方法寫的代碼:

1. this == obj, 毫無疑問,如果兩個對象的記憶體都是相同的話,那麼肯定是同一個對象了。2. this == null, 同樣的話,如果傳進來的對象是null的話,肯定為false。3. this.getClass == obj.getClass, 這個條件可能讓人有點疑惑。我來解釋一下,getClass是獲得當前的對象的Class對象,至於什麼是Class對象,這裡不解釋,需要的記得是:同一類的所有對象的獲得的Class對象都是同一個Class對象,也就是說,這裡的this如果obj不屬於同一個類的,那麼肯定為false。

    那麼這種寫法有好處呢,等我把在列出一個類的代碼再說吧!

public class Dog extends Animal{    private int age = 0;    public Dog(String name, int age) {        super(name);        this.age = age;    }    public int getAge() {        return age;    }    public void setAge(int age) {        this.age = age;    }        @Override    public boolean equals(Object obj) {        if(!super.equals(obj)) {            return false;        }        Dog dog = (Dog) obj;        return this.age == dog.age;    }}

    我們發現Dog類繼承於Animal類,並且重寫了父類的equals方法。在Dog類中equals方法,我們先來判斷了這兩個對象是否是相等的,其次再比較了age是否相同的。其中先調用了父類的equals來判斷,再來判斷子類本身的條件,這種方法有幾個好處:

1. 符合繼承的特性,若且唯若他們通過父類equals才有可能判斷子類的條件,因為如果不判斷父類的equals的話,當父類的equals返回的是false,但是通過調用子類的equals卻返回true。這個根本不符合物件導向的特性,實際點,如果兩個兒子老爸都不相同的話,兒子怎麼可能相同!2. 避免了obj是Dog類的子類(雖然這裡Dog類沒有子類)。因為這裡,我們先來調用父類的equals,父類的equals方法中:this.getClass() == obj.getClass 會協助我們判斷這兩個類是否是同一個類。按照我們以往的寫法,使用instanceof關鍵字來進行判斷的是有很大的問題的,如果this是Dog類的對象,但是obj的實際類型是Dog子類的對象,如果使用 obj instanceof Dog 這個返回的肯定為true,如果通過了我們這個判斷語句,最後來判斷我們的age。實際上,這兩個對象肯定不是同一個對象,所以最後用age來判斷是有問題的。至於這個問題的詳細解釋,待會還會提及!2. equals方法的特性

    上面留了一些伏筆,這裡將詳細的解釋,但是在解釋之前,我們先來看看equals方法的特性:

1. 自反性:對於任何的非Null 物件,x.equals(x)返回肯定為true。2. 對稱性:對於任何兩個非Null 物件x、y,如果x.equals(y)返回的是true,那麼y.equals(x)返回的是肯定也為true。3. 傳遞性:對於任何三個非Null 物件x、y、z,如果x.equals(y)為true,並且y.equals(z),那麼x.equals(z)肯定也為true。4. 一致性:如果對象x和對象y沒有發生任何變換的話,反覆調用y.equals(x)應該返回的是一樣的結果。5. 對於任意非Null 物件x,x.equals(null)應該返回的是false。

    針對這些特性,我們拿一個特性來解釋為什麼使用instanceof關鍵字來進行判斷有很大的問題。
    假設,記住這裡是假設:如果Animal類的equals方法和Dog類的equals方法使用的是instanceof關鍵字來判斷的,也就是下面的代碼:

Animal類的equals方法:
    @Override    public boolean equals(Object obj) {        if(!(obj instanceof Animal)) {            return false;        }        Animal animal = (Animal) obj;        return Objects.equals(this.name, animal.name);    }
Dog類的equals方法:
    @Override    public boolean equals(Object obj) {        if (!(obj instanceof Dog)) {            return false;        }        Dog dog = (Dog) obj;        return this.age == dog.age;    }
然後我們在main方法裡面這麼寫:
    public static void main(String[] args) {        Animal a1 = new Animal("pby");        Dog d1 = new Dog("pby", 21);        System.out.println(a1.equals(d1));        System.out.println(d1.equals(a1));    }

    我們可以看到的是第一個結果返回的true,但是第二個返回的false。這個就有問題了,不符合equals方法的對稱性。
    我們來分析一下,當a1.equals(d1)時,調用的Animal類中的equals方法,這個方法對name進行判斷,首先d1 instanceof Animal 肯定為true,因為Dog類是Animal的子類,所以if條件沒有屏蔽掉d1,由於兩個對象的name是相同的,所以傳回值是true,但是真正的結果是false,因為他們不屬於同一個類!至於第二個為什麼是false,這裡將不在解釋了!
    然後我們回來看正確寫法,this.getClass == obj.getClass這個判斷就能夠將我們的d1屏蔽掉!

Java基礎-equals方法

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.