看一個最簡單的annotation
package com.cts.elt.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
importjava.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyAnnotation1 {
String value();
}
1. Annotation需要聲明爲@interface這樣的東西
2. @Target(ElementType.TYPE)
代碼這個annotation必須且一定要註釋在什麼語句上面
ElementType.TYPE代表此Annotation必須聲明在public class Student{…}的上面,而不能寫在任何的method{}(方法)或者是field(屬性)的上方。
@Target: 表示該註解可以用於什麼地方。可用ElementType枚舉類型主要有:
TYPE : 類、接口或enum聲明
FIELD: 域(屬性)聲明
METHOD: 方法聲明
PARAMETER: 參數聲明
CONSTRUCTOR: 構造方法聲明
LOCAL_VARIABLE:局部變量聲明
ANNOTATION_TYPE:註釋類型聲明
PACKAGE: 包聲明
3. Retention如果設爲了RUNTIME,代表此annotation的具體實現可以在運行時用類反射來實現
我們看到了,annotation一般爲一個@interface,也沒啥具體的implementation(實現)
怎麼實現這個annotation呢?類反射
@Retention: 表示需要在什麼級別保存該註解信息。
可用RetentionPolicy枚舉類型主要有:
SOURCE: 註解將被編譯器丟棄。
CLASS : 註解在class文件中可能。但會被VM丟棄。
RUNTIME: VM將在運行時也保存註解(如果需要通過反射讀取註解,則
使用該值)。
4. @Documented
@Documented: 將此註解包含在Javadoc中。
上面這個MyAnnotation1.class文件包含一個值,下面來一個含有兩個值的annotation
package com.cts.elt.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
importjava.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyAnnotation2 {
String description();
boolean isAnnotation();
}
關鍵是來看這兩個自定義annotation的用法:
package com.cts.elt.annotation;
@MyAnnotation1("this isannotation1")
public class AnnotationDemo {
@MyAnnotation2(description = "this is annotation2", isAnnotation =true)
public void sayHello() {
System.out.println("hello world!");
}
}
如果把@MyAnnotation1與@MyAnnotation2的位置換一換,會怎麼樣?請自己動手在eclipse裏試試看,嘿嘿,就知道這個Retention的用法了
自定義annotation高級篇
首先,網上的一些關於自定義annotation教程所舉的例子都不太好!
就2個例子,然後一幫子人在那邊到處COPY這兩個例子然後到處轉發,搞得來大家雲裏霧裏一頭霧水,同時一羣企業的面試官也就喜歡拿這個自定義annotation來作面試題,好像會個annotation就能給Senior software engineer了。
其實Annotation就是類反射加點枚舉,比個數據結構裏的冒泡排序還簡單,沒這麼誇張,關鍵是例子舉的不好,現在來看看下面這個例子。
通過例子來看一個簡單的Annotation
Hibernate的機制是可能通過JAVA類然後逆向成數據庫裏的某個表,大家還記得吧?
比如說
Student.java文件
如果你這樣寫:
@Table(name=”T_STUDENT”)
Public class Student{…}
代表這個類對應的數據庫表叫T_STUDENT
如果再有下面這樣的寫法:
Public class Student{
Private String id=””;
@Id(init=1)
Public voidsetName(String id){
This.id=id;
}
}
就代表id這個field是一個主鍵,它的初始值爲1。
好了,現在開始我們自己的例子,設有一CLASS叫Student,其中有三個fields:
private String name = "";
private int age = 0;
private String studentId = "";
相應的每一個field有一對的set, get方法
然後我在每個set方法上造一個annotation叫ValueBind的註解,其作用是:
只要set方法上帶有ValueBind註解,它就會根據這個字段的類型把一個默認值,自動賦給Student類中相對應的field。
先來看一下Student類:
package com.cts.elt.annotation;
import java.io.Serializable;
importcom.cts.elt.annotation.ValueBind.fieldType;
public class Student implementsSerializable {
private String name = "";
public String getName() {
return name;
}
@ValueBind(type = fieldType.STRING, value ="aa")
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
@ValueBind(type = fieldType.INT, value ="30")
public void setAge(int age) {
this.age = age;
}
public String getStudentId() {
return studentId;
}
@ValueBind(type = fieldType.STRING, value ="101")
public void setStudentId(String studentId) {
this.studentId = studentId;
}
private int age = 0;
private String studentId = "";
}
自定義一個ValueBind的Annotation
這個@ValueBoind就是我的自定義的annotation,裏面有兩個值,來看這個annotation是怎麼做的吧:
package com.cts.elt.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
importjava.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ValueBind {
enum fieldType {
STRING, INT
};
fieldType type();
String value();
}
夠簡單的吧!
首先這個annotation只能被標註在方法上
其次它含有兩個值,一個是enum類型,一個是String類型
利用JAVA類反射來實現我們的Annotation
現在來看我們真正的實現(用類反射來實現)
package com.cts.elt.annotation;
import java.lang.reflect.*;
public class PersistStudent {
public static void main(String[] args) throws Exception {
Object c = Class.forName("com.cts.elt.annotation.Student")
.newInstance();
try {
Method[] methodArray = c.getClass().getDeclaredMethods();
for (int i = 0; i < methodArray.length; i++) {
if (methodArray[i].isAnnotationPresent(ValueBind.class)) {
ValueBind annotation = methodArray[i]
.getAnnotation(ValueBind.class);
String type = String.valueOf(annotation.type());
String value = annotation.value();
if (type.equals("INT")) {
methodArray[i].invoke(c, new Integer[] { new Integer(
value) });
} else {
methodArray[i].invoke(c, new String[] { value });
}
}
}
Student annotaedStudent = (Student) c;
System.out.println("studentId====" + annotaedStudent.getStudentId()
+ " studentnName====" + annotaedStudent.getName()
+ " student Age====" + annotaedStudent.getAge());
} catch (Exception e) {
throw new Exception(e);
}
}
}
運行完畢後顯示:
studentId====101 studentnName====aa studentAge====30