高階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.