J2SE5.0實例---註釋(annotation)

J2SE 5.0通過引入註釋(Annotation)的概念添加了對元數據的支持。

一個@xxx形式的註釋可以當成一個修飾符來使用,它可以放在任何一個修飾符可以出現的地方。public,static,final都是java語言的修飾符,註釋可以寫在它們可以出現的任何地方。

舉個例子,可以看下面一段代碼:

public class AnnotationExample {

    public @Override int hashCode() {

       return super.hashCode();

    }

}

 

在這個例子中我們使用了一個java語言API中已經有定義的註釋@Override,通過在方法hashCode()中使用這個註釋,說明了hashCode是一個覆蓋了父類方法的方法。

至於註釋的具體含義我們在以後部分會說明。

如果你想使用一個類,你必須首先找到它的定義,或者你自己對它進行定義。註釋也是需要定義的,隨便在代碼中插入一個@XXX之類的註釋是不能夠通過編譯的。

一個最簡單的Annotation定義類似於接口的定義,就象下面的代碼:

public @interface Info {

}

 

正如你所看到的,裏面什麼都沒有,但是即使是這樣,我們也可以在程序裏使用它:

public @Info String  information;

 

這樣的一種什麼都沒有定義的空註釋我們稱爲標記註釋(marker annotations

我們可以在其中添加一個成員的定義:

public @interface Info {   

     String author();

}

 

這裏值得注意的一點是,註釋類中方法的定義不能是私有的,如果你不在前面加public關鍵字,編譯器會默認爲它是公有的。

在添加上author的定義後,原來那種只寫了一個@Info的註釋就必須修改了,之後的註釋必須這樣寫:

public @Info(author="myname")  void afunction() {

}

 

一個註釋的成員可以有默認值:

public @interface Info {   

     String author() default "myname";

}

 

使用默認值有什麼好處呢?我們可以重新這樣寫了:

public @Info  void afunction() {

}

 

在做標記時,如果確認某個成員的值和它的默認值相同,我們就可以忽略它,而不必顯式地給每個成員賦值,這樣就減輕了代碼量。

如果我們添加的這個成員名字叫做value的話,也就是:

public @interface Info {   

     String value();

}

 

就有了另外一種註釋的用法: 我們可以直接寫出這樣的註釋@Info(“information”),而不必寫@Info(value=”information”),括號裏的值會自動傳遞給value。這樣的一種註釋稱爲單一值註釋(Single-value annotations

一個註釋可以有很多類型不同的成員,這樣的一種註釋稱爲完整註釋(full annotations

一個註釋中的成員類型只能夠是原生類型,字符串,Class類型,註釋類型,枚舉類型,或者一維數組。

假設我們現在有一個註釋定義:

public @interface Company {

    String value();

}

 

現在我們希望定義另外一個註釋,這個註釋類型反映了一個人的信息:

public @interface Person {

    public enum Gender{MALE,FEMALE};

   

    String name();

    int age();

    Company company();

    Gender gender() default Gender.MALE;

    String description() default "";

}

 

在程序代碼中添加這種類型的註釋時可以這麼寫:

@Person(age=23,name="MyName",gender=Person.Gender.FEMALE, company=@Company("Foo Corporation"))

 

java.lang包中定義了三種註釋,分別是:

n         Deprecated:和過去javadoc@deprecated含義相同

n         Override:表示方法覆蓋了父類中的方法

n         SuppressWarnings:使用這個註釋可以使編譯器忽略特定類型的警告信息

具體含義可以參照api文檔。

我們知道,註釋的引入,爲java語言添加了元數據的表達方式,而元數據就是關於數據的數據。在java中,還有關於註釋的註釋,我們相應的稱之爲元註釋(meta-annotations

java中,我們可以使用4種預先定義的註釋對註釋定義進行註釋,這4種註釋是:

n         Target:指明註釋可以在哪些代碼段中使用,以避免對註釋的誤用。

n         Retention:說明編譯器在編譯和運行時是否忽略該種註釋

n         Documented:說明註釋是否出現在Javadoc

n         Inherited:當我們在一個類中使用了某種註釋,有時候會希望將來它的所有子類中都包含有該種註釋信息,如果在註釋定義中添加了@Inherited,那麼這種註釋就會被調用者的子類繼承

當我們在一個類中使用註釋定義了一系列的元數據之後,我們應該如何獲取這些元數據呢?我們通過下面的例子來說明。

Annotation的定義仍然使用列出來的兩個,因爲我們需要在獲得類文件中的註釋信息,所以必須在註釋定義中添加Retention註釋。

首先我們定義兩個註釋,註釋Todo說明了還有什麼事情需要做:

import java.lang.annotation.Retention;

import java.lang.annotation.RetentionPolicy;

 

@Retention(RetentionPolicy.RUNTIME)

public @interface Todo {

    String value();

}

 

註釋Author說明了一個方法或者類的定義者:

import java.lang.annotation.Retention;

import java.lang.annotation.RetentionPolicy;

 

@Retention(RetentionPolicy.RUNTIME)

public @interface Author {

    public enum Gender{MALE,FEMALE};

 

    String name();

    String email();

    Gender gender() default Gender.MALE;

}

 

然後我們在一個簡單的類中添加這兩種類型的註釋:

public @Todo("delete this class") class Foo {

   

    public void methodA(){}

    public @Author(name="B",email="[email protected]") void methodB(){

    }

   

    public @Author(name="A",email="[email protected]") String  fieldA;

}

 

通過下面一段代碼我們可以提取相應的元數據:

import java.lang.reflect.Method;

 

public class GetAnnotations {

 

    public static void main(String[] args) {

       try {

           Class<?> klass=Class.forName(args[0]);

           if(klass.isAnnotationPresent(Todo.class))

           {

              Todo t=klass.getAnnotation(Todo.class);

              System.out.println(t);

           }

           for(Method m:klass.getMethods())

           {

              if(m.isAnnotationPresent(Author.class))

              {

                  Author a=m.getAnnotation(Author.class);

                  System.out.printf("Method:%s,Author:%s%n",m.getName(),a);

              }

           }

       } catch (ClassNotFoundException e) {

          

           e.printStackTrace();

       }

    }

}

 

 

使用下面的命令行運行程序:

java GetAnnotations Foo

 

運行結果如下:

@Todo(value=delete this class)

Method:methodB,Author:@Author(gender=MALE, name=B, [email protected])

 

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