高階Java-Java註解 Java annotation 使用詳解

高階Java-Java註解 Java annotation 使用詳解

文章分類:Java編程

來越的開源框架都提供了“元數據”支持了。爲了不outdate,今天系統學習一下Java的註釋(又叫元數據)。本文將遵循以下的結構佈局
1.什麼是元數據?有什麼作用
2.Java的“註釋”
3.在Java中定義自己的註釋
4.總結一下

-----------------------開始----------------------


1.什麼是元數據,有什麼作用?


元數據,就是“關於數據的數據”。功能也有很多啦。你可能用過Javadoc的註釋自動生成文檔。這就是元數據功能的一種。總的來說,元數據可以用來創建文檔,跟蹤代碼的依賴性,執行編譯時格式檢查,代替已有的配置文件(如Hibernate也提供了註釋配置)

註釋有3中基本類型

a.標記註釋      --沒有變量,只有名稱標識。例如 @annotation
b.單一值註釋    --在標記註釋的基礎上提供一段數據。如 @annotation(“data”)
c.完整註釋      --可以包括多個數據成員,每個數據成員由名稱和值構成。
                  @annotation(val1="data1",val2="data2")

2.Java的“註釋”

Java中提供3個內置註釋類型

a. Override ,只能用於方法(不能用於類,包聲明或者其他構造)
              作用:可以保證編譯時候Override函數的聲明正確性
              用法:@Override
                    public void fun(){..}

b.Deprecated  同樣只能作用與方法
              作用:對不應再使用的方法進行註解
              用法:@Deprecated public void fun{...} //它們說這個註釋跟函數要同一行

c.SupressWarnings 可以註釋一段代碼
                  作用:關閉特定的警告信息,例如你在使用泛型的時候未指定類型
                  用法: @SupressWarnings(value={"unchecked"})
                         ..代碼

Java中還提供了四種元註釋,專門負責註釋其他的註釋

@Target   表示該註釋可以用於什麼地方。可用的ElementType參數包括:
          CONSTRUCTOR : 構造器的聲明
          FIELD : 域聲明(包括enum實例)
          LOCAL_VARIABLE : 局部變量聲明
          METHOD : 方法聲明
          PACKAGE : 包聲明
          PARAMETER : 參數聲明
          TYPE : 類、接口 (包括註解類型) 或enum聲明

@Retention 表示需要在什麼級別保存該註釋信息。可選的RetentionPoicy參數包括:
           SOURCE : 註釋將被編譯器丟掉
           CLASS : 註釋在class文件中可用,但會被VM丟棄
           RUNTIME : VM將在運行時也保留註釋,因此可以通過反射機制讀取註釋的信息。

@Documented 將註釋包含在JavaDoc中

@Inheried  允許子類繼承父類中的註釋。

3. 在Java中定義自己的註釋

Java語言支持一種新的類型--註釋類型(annotation type),跟普通類差不多,在類中以符號( @ )的形式註釋其他 Java 代碼

下面將通過一個簡單的例子來實現(代碼是Brett McLaughlin 的)

@interface 申明

i.簡單的註釋類型
package com.oreilly.tiger.ch06;
/**
 * Marker annotation to indicate that a method or class
 * is still in progress.
 */
public @interface InProgress { }

ii.使用定製的註釋類型
@com.oreilly.tiger.ch06.InProgress
public void calculateInterest(float amout,float rate)
{
      //Need to finish this method later
}

iii.添加成員
package com.oreilly.tiger.ch06;
/**
 * Marker annotation to indicate that a method or class
 * is still in progress.
 */
public @interface InProgress {
  String value();
 }

@com.oreilly.tiger.ch06.InProgress
@TODO("Figure out the amount of interest per month")
//或者@TODO(value="Figure out the amount of interest per month")
public void calculateInterest(float amount,float rate)
{
}

iv.設置默認值
package com.oreilly.tiger.ch06;
public @interface GroupTODO {
  public enum Serverity { CRITICAL,IMPORTANT,IRIVIAL,DOCMENTATION };
  Severity severity()
          default Severity.IMPORTANT;
  String item ();
  String assignedTo();
  String dateAssigned();
}
}

v.使用默認值
@com.oreilly.tiger.ch06.InProgress
@GroupTODO(
 item="Figure out the amount of interest per month",
 assignedTo = "Brett McLaughlin",
 dateAssigned = "08/04/2004"
)

public void calculateInterest(float amount, float rate)
{
   //Need to finish this method later
}

vi.改寫默認值
@com.oreilly.tiger.ch06.InProgress
@GroupTODO
{
   severity = GroupTODO.Severity.DOCUMENTATION,
   item = "Need to explain how this rather unusal method works",
   assignedTo = "Jon Stevens",
   dateAssigned = "07/30/2004"
}

 

【轉至】:http://blog.csdn.net/janeky/archive/2009/09/19/4570541.aspx

 

 

核心提示:註解(也被稱爲元數據)爲我們在代碼中添加信息提供了一種形式化的方法,使我們可以在稍後某個時刻非常方便地使用這些數據。
Java基礎-學習使用Annotation註解對象
註解(也被稱爲元數據)爲我們在代碼中添加信息提供了一種形式化的方法,使我們可以在稍後某

個時刻非常方便地使用這些數據
 
1-1:基本語法
Java SE5內置三種標準註解
@Override:表示當前的方法定義將覆蓋超類中的方法.如果你不小心拼寫錯誤,或者方法簽名對不上被覆

蓋的方法,編譯器就會發出錯誤提示

@Deprecated:如果程序員使用了註解爲它的元素,那麼編譯器就會發出警告信息

@SupperessWarnings:關閉不當的編譯器警告信息.

Java SE5內置四種元註解
@Target:表示該註解可以用於什麼地方.可能的ElementType參數包括:
1)CONSTRUCTOR:構造器的聲明
2)FIELD:域聲明(包括enum實例)
3)LOCAL_VARIABLE:局部變量聲明
4)METHOD:方法聲明
5)PACKAGE:包聲明
6)PARAMETER:參數聲明
7)TYPE:類、接口(包括註解類型)或enum聲明

@Retention:表示需要在什麼級別保存該註解信息.可選的RetentionPolicy參數包括:
1)SOURCE:註解將被編譯器丟棄
2)CLASS:註解在class文件中可用,但會被VM丟棄
3)RUNTIME:VM將在運行期也保留註解,因此可以通過反射機制讀取註解的信息

@Documented:將此註解包含在Javadoc中

@Inherited:允許子類繼承父類中的註解
大多數時候,程序員主要是定義自己的註解,並編寫自己的處理器來處理它們.

----------------------------- UseCase.java -------------------------   
package com;   
  
import java.lang.annotation.ElementType;   
import java.lang.annotation.Retention;   
import java.lang.annotation.RetentionPolicy;   
import java.lang.annotation.Target;   
  
@Target(ElementType.METHOD)//用來定義你的註解將應用在什麼地方,本處應用爲方法   
//用來定義該註解在哪一個級別可用,在源代碼中(source)類文件中(class)或者運行時(runtime)   
@Retention(RetentionPolicy.RUNTIME)   
public @interface UseCase {   
 public int id();   
 public String description()default "no description";   
}   
  
----------------------------- PasswordUtils .java -------------------------   
package com;   
  
public class PasswordUtils {   
 @UseCase(id=47,description="Passwords must contain at least one numeric")   
 public boolean validatePassword(){   
  return true;   
 }   
    
 @UseCase(id=48)   
 public String encryptPassword(String password){   
  return  password;   
 }   
    
 @UseCase(id=49,description="Jong_Cai")   
 public void showName(){   
  System.out.println("Jong_Cai");   
 }   
}   
  
1-2:編寫註解處理器
 如果沒有用來讀取註解的工具,那註解也不會比註釋更有用.使用註解的過程中.很重要的一個部

分就是創建與使用註解處理器.Java SE5擴展了反射機制的API,以幫助程序員構造這類工具.同時,它還提

供了一個外部工具apt幫助程序員解析帶有註解的Java源代碼.
 下面是一個非常簡單的註解處理器,我們將用它來讀取PasswordUtils類,並使用反射機制查

找@UseCase標記.我們爲其提供了一組id值得,然後它會列出在PasswordUtils中找到的用例,以及缺失的

用例.

------------------------ UseCaseTracker.java ---------------------------   
package com;   
  
import java.lang.reflect.Method;   
import java.util.ArrayList;   
import java.util.Collections;   
import java.util.List;   
  
public class UseCaseTracker {   
 public static void trackUseCases(List<Integer> list, Class<?> cl) {   
  for (Method m : cl.getDeclaredMethods()) {   
   UseCase us = m.getAnnotation(UseCase.class);   
   if (us != null) {   
    System.out.println("Found Use Case:" + us.id() + " "  
      + us.description());   
    list.remove(new Integer(us.id()));   
   }   
  }   
  for (int i : list) {   
   System.out.println("Warning:Missing use case-" + i);   
  }   
 }   
  
 public static void main(String[] args) {   
  List<Integer> list = new ArrayList<Integer>();   
  Collections.addAll(list, 47,48,49,50,51);   
  trackUseCases(list, PasswordUtils.class);   
 }   
}   
  
 這個程序用到了兩個反射的方法:getDeclaredMethods()和getAnnotation(),它們都屬

於AnnotatedElement接口(class,Method與Field等類都實現了該接口).getAnnotation()方法返回指定類

型的註解對象,在這裏就是UseCase,如果被註解的方法上沒有該類型的註解,則返回null值.然後我們通過

調用id()和description()方法從返回的UseCase對象中提取元素的值.其中encryptPassword()方法在注

解的時候沒有指定description的值,因此處理器在處理它對應的註解時,通過description()方法取得的

是默認值no description.

 

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