Java五種基本的Annotation,提高程序的可讀性
從JDK5開始,Java增加了對元數據的支持,也就是Annotation(即註解也被翻譯為註釋)。
這裏的Annotation和普通的註釋有一定的區別,它是代碼中的特殊標記,這些標記可以在編譯、類加載或者運行時被讀取,並執行相應的處理。通過這樣的註解,可以幫助開發人員在不改變原有的邏輯的情況下,在源文件中補充一些信息。而代碼分析工具、開發工具和部署工具可以通過這些補充信息進行驗證或者進行部署。
Annotation可以用來為程序元素(類、方法、成員變量等)設置元數據,值得一提的是,它不會影響代碼的執行。
Java提供了5個基本Annotation的用法——使用Annotation時要在其前面增加@符號,並把該Annotation當成一個修飾符來使用。
5個基本的Annotation如下:
- @Override
- @Deprecated
- @SuppressWarnings
- @SafeVarargs
- @FunctionalInterface
@Override
@Override用來指定子類必須覆蓋父類的方法
public class Fruit { public void info(){ System.out.println("Fruit"); } } class Apple extends Fruit{ @Override public void info(){ System.out.println("Apple"); } }
編譯上面的程序,可能絲毫看不出@Override的用處所在,因為它的作用是告訴編譯器檢查這個方法,保證父類要包含一個被該方法重寫的方法,否則會編譯出錯。
使用@Override可以避免開發人員不小心將info方法寫成了inf0方法,這樣的低級錯誤可能會成為後期排錯時的巨大障礙。
@Deprecated
@Deprecated用來表示某個程序元素(類、方法等)已經過時,當其他程序使用已經過時的類或者方法時,編譯器將會給出警告。
@SuppressWarnings
@SuppressWarnings指示由它修飾的程序元素以及該元素中的所有子元素取消顯示指定的編譯器警告。
@SuppressWarnings(value="all") public class Fruit { public static void main(String[] args){ Fruit.info(); } @Deprecated public static void info(){ System.out.print("Fruit"); } }
參考上面的代碼,當使用了“@SuppressWarnings(value=”all”)”之後,編譯器會取消使用了已經被棄用的方法的警告。value變量的值為你希望抑制的警告。
“堆汙染”警告與@SafeVarargs
List ls = new ArrayList<Integer>();
ls.add(20);//添加元素時會引發unchecked警告
//下面的代碼會引發“未經檢驗的轉換”的警告,但是編譯、運行時完全正常
List<String> list = ls;
//但是只要訪問其中的元素,下面代碼就會引起運行時異常
System.out.print(list.get(0));
Java將引發這種錯誤的原因稱為“堆汙染”。當把一個不帶泛型的對象賦給一個帶泛型的對象時,往往就會產生這種“堆汙染”。
class UnSafeVarargs
{
static <T> T[] foo(T... args) {
return args;
}
static <T> void bar(T... args) {
for(T x : args) {
System.out.print(x);
}
}
}
考慮上面這段程序,編譯器會在方法定義處提示“Possible heap pollution from parameterized vararg type”。這是因為對於形參的個數可變且又是泛型時,當後續的代碼依賴於傳入的args中的每個元素的話,它是安全的。如果後續的代碼依賴於args整體是T類型的數組的話,它將是不安全的。因為其中的元素可能是整型,也可能是字符串。程序會嘗試將它轉換成一個T類型的數組並且失敗。
因此上面的兩個方法中,前者是不安全的,後者是安全的。
在有些時候,開發者不希望看到這個“堆汙染”的警告,那麽就可以使用以下三種方式來抑制這個警告:
- 使用@SafeVarargs修飾引發該警告的方法或者構造器
- 使用@SuppressWarnings(“unchecked”)修飾。
- 編譯時使用-Xlint:varargs選項
顯然第三種方式很少用到,通常選擇前兩種,尤其是第一種,因為它是專門為抑制“堆汙染”警告而提供的。
@FunctionalInterface
如果接口中只有一個抽象方法(可以包括多個默認方法或者多個static方法),該接口就是函數式接口。@FunctionalInterface就是用來指定某個接口必須是函數式接口的。
如果使用了@FunctionalInterface的接口不是函數式接口,那麽編譯就會出錯。它和@Override一樣,都是為了幫助程序員避免一些低級錯誤的。
Java五種基本的Annotation,提高程序的可讀性