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 的版本中加入的。
br/>@FunctionalInterface
函數式接口註解,這個是 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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章