1. 程式人生 > >Java開發筆記(八十一)如何使用系統自帶的註解

Java開發筆記(八十一)如何使用系統自帶的註解

多余 vat 除了 內部 warn 父類 方法名 普通 註意

之前介紹繼承的時候,提到對於子類而言,父類的普通方法可以重寫也可以不重寫,但是父類的抽象方法是必須重寫的,如果不重寫,編譯器就直接在子類名稱那裏顯示紅叉報錯。例如,以前演示抽象類用法之時,曾經把Chicken雞類的call方法改為抽象方法,方法聲明代碼如下所示:

	// 定義一個抽象的叫喚方法。註意後面沒有花括號,並且以分號結尾
	abstract public void call();

倘若派生自雞類的公雞類沒有重寫call方法,編譯器除了紅叉報錯以外,還會彈出提示“Add unimplemented method”,也就是建議開發者為公雞類補充實現call方法。按照建議點擊提示文字,eclipse會自動在公雞類中添加以下的默認代碼:

	@Override
	public void call() {
		// TODO Auto-generated method stub
	}

註意到新增的call方法上面一行,多出了形如“@Override”的標記,該標記看起來似乎是多余的,即使把它刪掉,編譯器也不會報錯,程序也能正常運行。莫非“@Override”是另一種形式的註釋?實際上,以@符號開頭的標記,它們的真正名稱叫做“註解”,跟“註釋”僅有一字之差,二者的關系恰如名字那樣,既有相同點又有不同點。相同點為:註解一樣帶有解釋說明的涵義,比如Override翻譯成中文就是“重寫”的意思,表示標記下方的call方法重寫了父類的抽象方法。不同點為:註釋是給人看的,而註解還要給編譯器看,編譯器掃描到註解@Override,便會去檢查父類是否存在註解下方的方法聲明,如果不存在或者參數類型對不上,就會提示紅叉錯誤。

除了方法重寫註解“@Override”之外,還有一種常見的註解叫“@FunctionalInterface”,翻譯成中文便是“函數式接口”,猜的沒錯,該註解專門用來標記Java8規定的函數式接口。函數式接口是一類特殊的接口形式,它的內部有且僅有一個抽象方法,抽象方法多了不行,再來一個抽象方法的話,接口實例就沒法簡寫為Lambda表達式,也就無法成為“函數式”接口。Java自帶的幾個函數式接口包括:比較器Comparator、斷言接口Predicate、消費接口Consumer、函數接口Function、文件過濾器FileFilter、運行器Runnable等等,查看它們的源碼,會發現接口定義的上方無一例外都存在註解“@FunctionalInterface”。例如下面是比較器Comparator的核心定義代碼:

//該註解表示以下定義的是函數式接口,有且僅有一個抽象方法聲明。
//如果同時聲明了多個抽象方法,則編譯器在編碼階段就會報錯。
@FunctionalInterface
public interface Comparator<T> {
    int compare(T o1, T o2);
    
	// 此處省略比較器接口的剩余代碼定義
}

@FunctionalInterface註解明白無誤地告訴編譯器,它的下方接口是個函數式接口,請務必檢查這個接口定義是否符合函數式接口的要求。編譯器根據註解的指示,立即掃描註解下方的接口代碼,並仔細統計接口內部的抽象方法個數,倘若抽象方法的數量不足一個或者多於一個,編譯器都會提示錯誤“Invalid ‘@FunctionalInterface‘ annotation; *** is not a functional interface”,意思是“註解@FunctionalInterface是無效的,因為***不是一個函數式接口”,這樣正好提醒開發者檢查接口定義是否存在問題。
第三種常見的註解名叫“@Deprecated”,早前介紹日期工具Date的時候,在代碼中調用日期實例的getYear、getMonth、getDate等方法,這幾個方法的名稱中間居然出現了一條刪除線。查看相關日期方法的源碼,才發覺它們的定義代碼上方聳立著註解“@Deprecated”,該註解的含義是“不贊成、已廢棄”,緣由是Java認為這幾個日期方法已經過時了,隨時都會從開發包中移除,建議開發者將它們替換成日歷工具裏的對應方法。盡管目前仍然可以在代碼中調用這些過時的方法,但是編譯器依舊按照規定在方法名稱中間顯示刪除線,並且還會給出警告“Add @SupressWarnings ‘deprecated‘ to ‘***‘”。這警告說的是建議往***添加註解“@SupressWarnings”(含義為屏蔽警告),從而避免此處的警告提示。正所謂“眼不見心不煩”,那就按照建議在日期方法的調用處統統添加新註解“@SuppressWarnings("deprecation")”,添加完了,果然這些“已過時”的警告都被屏蔽掉了。
註解@SuppressWarnings不僅可用來屏蔽“已過時”的警告,還能用來屏蔽其它類型的警告,譬如“未使用”這類警告。上一篇文章演示私有方法的反射調用之時,給Chicken類增加了setName、getName、setSex、getSex四個私有方法,這些方法並未被Chicken類自身所調用,編譯器會認為它們是“未使用”的方法,因而在這四個方法的定義處提示警告信息“Remove method ‘***‘”,也就是建議刪除某某某方法。如果程序員仍想保留這些方法,又不想看到警告提示,則可在Chicken類上方添加註解“@SuppressWarnings("unused")”,表示屏蔽未使用的警告。添加了@SuppressWarnings註解的雞類定義代碼片段示例如下:

//該註解表示屏蔽“未使用”這種警告
@SuppressWarnings("unused")
abstract public class Chicken {
	// 此處省略雞類的其它代碼定義

	private void setName(String name) { // 設置名稱
		this.name = name;
	}

	private String getName() { // 獲取名稱
		return this.name;
	}

	private void setSex(int sex) { // 設置性別
		this.sex = sex;
	}

	private int getSex() { // 獲取性別
		return this.sex;
	}
}

上面的四種註解中,@Override、@Deprecated、@SuppressWarnings這三種是從Java5開始引入的,而@FunctionalInterface是在Java8才引入的。除此之外,Java7還引入了第五種註解名叫“@SafeVarargs”,主要目的是兼容可變參數中的泛型參數,該註解告訴編譯器:此處可變參數中的泛型是類型安全的,不必擔心強制類型轉換的問題。由於前述的五種註解是系統提供給開發者使用的,因此它們被統稱為“內置註解”。



更多Java技術文章參見《Java開發筆記(序)章節目錄》

Java開發筆記(八十一)如何使用系統自帶的註解