Java——註解詳解
Java註解同 classs 和 interface 一樣,註解也屬於一種型別。它是在 Java SE 5.0 版本中開始引入的概念。
註解的定義
通過 @interface 關鍵字進行定義。
public @interface TestAnnotation {
}
這段程式碼就建立了一個名字為 TestAnnotaion 的註解。
你可以簡單理解為建立了一張名字為 TestAnnotation 的標籤。
使用註解
@TestAnnotation
public class Test {
}
在類上加上@TestAnnotation 就可以用 TestAnnotation 註解這個類了。
內建註解
@Deprecated、@Override、@SuppressWarnings、@SafeVarargs、@FunctionalInterface
@Deprecatedbr/>這個元素是用來標記過時的元素,編譯器在編譯階段遇到這個註解時會發出提醒警告,告訴開發者正在呼叫一個過時的元素比如過時的方法、過時的類、過時的成員變數。
@Override
提示子類要複寫父類中被 @Override 修飾的方法br/>@SuppressWarnings
阻止警告的意思,把警告取消。br/>@SafeVarargs
引數安全型別註解。它的目的是提醒開發者不要用引數做一些不安全的操作,它的存在會阻止編譯器產生 unchecked 這樣的警告。它是在 Java 1.7 的版本中加入的。
函式式介面註解,這個是 Java 1.8 版本引入的新特性,函數語言程式設計。
函式式介面 (Functional Interface) 就是一個具有一個方法的普通介面。
元註解
元註解是可以註解到註解上的註解,或者說元註解是一種基本註解,但是它能夠應用到其它的註解上面。
有 @Retention、@Documented、@Target、@Inherited、@Repeatable 5 種。
@Retention
當 @Retention 應用到一個註解上的時候,它解釋說明了這個註解的的存活時間。
它的取值如下:
RetentionPolicy.SOURCE 註解只在原始碼階段保留,在編譯器進行編譯時它將被丟棄忽視。
RetentionPolicy.CLASS 註解只被保留到編譯進行的時候,它並不會被載入到 JVM 中。
RetentionPolicy.RUNTIME 註解可以保留到程式執行的時候,它會被載入進入到 JVM 中,所以在程式執行時可以獲取到它們。
@Documented
它的作用是能夠將註解中的元素包含到 Javadoc 中去。
@Target
@Target 指定了註解運用的地方。當一個註解被 @Target 註解時,這個註解就被限定了運用的場景。
ElementType.ANNOTATION_TYPE 可以給一個註解進行註解
ElementType.CONSTRUCTOR 可以給構造方法進行註解
ElementType.FIELD 可以給屬性進行註解
ElementType.LOCAL_VARIABLE 可以給區域性變數進行註解
ElementType.METHOD 可以給方法進行註解
ElementType.PACKAGE 可以給一個包進行註解
ElementType.PARAMETER 可以給一個方法內的引數進行註解
ElementType.TYPE 可以給一個型別進行註解,比如類、介面、列舉
@Inherited
Inherited 是繼承的意思,但是它並不是說註解本身可以繼承,而是說如果一個類使用了被Inherited標註的註解,那麼這個類的子類也繼承這個註解。
@Repeatable
Repeatable是可重複的意思,註解容器。@Repeatable 是 Java 1.8 才加進來的,所以算是一個新的特性。
@interface Persons {
Person[] value();
}
@Repeatable(Persons.class)//相當於用來儲存該註解內容的容器。
@interface Person{
String role default "";
}
@Person(role="teach")br/>@Person(role="coder")
@Person(role="PM")
public class Man{
}
註解的屬性
註解的屬性也叫做成員變數。註解只有成員變數,沒有方法。註解的成員變數在註解的定義中以“無形參的方法”形式來宣告,其方法名定義了該成員變數的名字,其返回值定義了該成員變數的型別。
public @interface TestAnnotation {
int id();
String value();br/>}
使用註解
@TestAnnotation(id=1,value="xxxxx")
public class Test {
}
註解中屬性可以有預設值,預設值需要用 default 關鍵值指定。
public int id() default -1;
注:
如果一個註解內只有一個屬性時,使用註解時可以直接接屬性值填寫到括號內。
如果沒有屬性,使用的時候可以省略括號。
註解的提取
一個註解要在執行時被成功提取,那麼 @Retention(RetentionPolicy.RUNTIME) 是必須的。
註解通過反射獲取。首先可以通過 Class 物件的 isAnnotationPresent() 方法判斷它是否應用了某個註解
public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) {}
然後通過 getAnnotation() 方法來獲取 Annotation 物件。public <A extends Annotation> A getAnnotation(Class<A> annotationClass) {}
或者是 getAnnotations() 方法。public Annotation[] getAnnotations() {}
前一種方法返回指定型別的註解。
後一種方法返回應用到這個元素上的所有註解。
例子
@Retention(RetentionPolicy.RUNTIME)
public @interface TestAnnotation {
public int id() default 2;
public String value() default "hello";
}
@TestAnnotation
public class AnnotationTest {
public static void main(String[] args) throws ClassNotFoundException {
//Class c = Class.forName("com.temp.annotation.AnnotationTest");
boolean hasAnnotation = AnnotationTest.class.isAnnotationPresent(TestAnnotation.class);
if (hasAnnotation ) {
TestAnnotation testAnnotation = AnnotationTest.class.getAnnotation(TestAnnotation.class);
Annotation[] ans = AnnotationTest.class.getAnnotations();
System.out.println(ans[0]);
System.out.println("id:"+testAnnotation.id());
System.out.println("value:"+testAnnotation.value());
}
}
}
執行結果:
@com.temp.annotation.TestAnnotation(value=hello, id=2)
id:2
value:hello