第36條 堅持使用Override注解

考慮下面的程序,類Bigram 表示一個雙字母組,考慮打印語句的輸出結(jié)果

package thirtysix;
import java.util.HashSet;
import java.util.Set;
/**
 * Bigram
 * @author ZHAIYANMING
 * @version 1.0
 *
 */
public class Bigram {
    private final char first;
    private final char second;

    public Bigram(char first, char second) {
        this.first = first;
        this.second = second;
    }

    public boolean equals(Bigram bigram) {
        return bigram.first == first && bigram.second == second;
    }

    public int hashCode() {
        return 31 * first + second;
    }

    public static void main(String[] args) {
        Set<Bigram> bigrams = new HashSet<Bigram>();
        for (int i = 0; i < 10; i++) {
            for (char ch = 'a'; ch <= 'z'; ch++) {
                bigrams.add(new Bigram(ch, ch));
            }
        }
        System.out.println(bigrams.size());
    }
}

為什么結(jié)果是這樣?bigrams采用的集合類型是HashSet,為什么沒有去掉重復(fù)的元素呢?

/**
     * Adds the specified element to this set if it is not already present.
     * More formally, adds the specified element <tt>e</tt> to this set if
     * this set contains no element <tt>e2</tt> such that
     * <tt>(e==null ? e2==null : e.equals(e2))</tt>.
     * If this set already contains the element, the call leaves the set
     * unchanged and returns <tt>false</tt>.
     *
     * @param e element to be added to this set
     * @return <tt>true</tt> if this set did not already contain the specified
     * element
     */
    public boolean add(E e) {
        return map.put(e, PRESENT)==null;
    }

HashSet的add方法的底層說明:3~5行說明了add元素e的條件:set中不存在元素e2( e==null;e2==null;e.equals(e2) )。在元素都不為null的情況下,說明這行代碼e.equals(e2) 與我們想要的結(jié)果不一樣.

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

看一下Object類中的equals方法。發(fā)現(xiàn)代碼中原本想要覆蓋equals方法(發(fā)生覆蓋的條件:“三同一不低”,子類和父類的方法名稱,參數(shù)列表,返回類型必須完全相同,而且子類方法的訪問修飾符的權(quán)限不能比父類低。),可是卻重載了equals方法(發(fā)生重載的條件:方法名相同,參數(shù)列表(類型、個數(shù)、順序)不同)。在進(jìn)行這行代碼( e.equals(e2) )時,就調(diào)用了Object類的equals方法,而Object類的equals方法是比較對象同一性的,即( e==e2 )。例子中:這行代碼:bigrams.add(new Bigram(ch, ch)); 每次添加都會new Bigram(ch,ch),每一個Object都不一樣,自然循環(huán)多少次,就add多少Object了。
隨著java 1.5發(fā)行版本中增加注解,類庫中也增加了幾種注解類型。其中Override只能用在方法聲明中,它表示被注解的方法聲明覆蓋了超類型中的一個聲明。堅持使用這個注解,可以防止一大類非法錯誤。

    @Override public boolean equals(Bigram bigram) {
        return bigram.first == first && bigram.second == second;
    }

如果插入這個注解,重新編譯程序,編譯器會產(chǎn)生一條錯誤:

The method equals(Bigram) of type Bigram must override or implement a supertype method

針對提示的錯誤咱們就可以修改相應(yīng)的代碼,這個equals方法測試對象的同一性,就像==:

@Override public boolean equals(Object o) {
        if(!(o instanceof Bigram)) {
            return false;
        }
        Bigram b = (Bigram) o;
        return b.first == first && b.second == second;
    }

總結(jié):如果在你想要的每個方法聲明中使用 Override 注解來覆蓋超類聲明 , 編譯器就可以替你防止大量錯誤 。在具體的類中 , 不必標(biāo)注你確信覆蓋了抽象方法聲明的方法(標(biāo)注也可以)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法,類相關(guān)的語法,內(nèi)部類的語法,繼承相關(guān)的語法,異常的語法,線程的語...
    子非魚_t_閱讀 34,638評論 18 399
  • 一、基本數(shù)據(jù)類型 注釋 單行注釋:// 區(qū)域注釋:/* */ 文檔注釋:/** */ 數(shù)值 對于byte類型而言...
    龍貓小爺閱讀 4,441評論 0 16
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,534評論 19 139
  • Java 語言支持的類型分為兩類:基本類型和引用類型。整型(byte 1, short 2, int 4, lon...
    xiaogmail閱讀 1,445評論 0 10
  • 人都一定會生氣,這是一個很顯然的問題, 小孩子也是會生氣,因?yàn)樾『⒆右彩侨耍瑫驗(yàn)楸幌拗朴螒蚨蠛?,也會因?yàn)楸皇箚?..
    愛霖心理閱讀 246評論 5 1

友情鏈接更多精彩內(nèi)容