java自定義註解
1.註解分類:
按運行機制分:
SOURCE源碼註解:註解只在源碼中存在,編譯成.class文件就不存在了
CLASS編譯時註解:註解在源碼和.class文件都存在,但運行時會被移除
(@Override,@Deprecated,@SuppressWarnings)
RUNTIME運行時註解:表示這個註解會保留到運行時,甚至還會影響運行邏輯
(@Autowired)
按來源分:
內置註解(@Override,@Deprecated,@SuppressWarnings)
第三方註解
自定義註解
2.元註解(註解的註解):
@Retention
定義註解的生命週期,可選值爲source、class、runtime
@Documented
文檔化註解,會被javadoc工具文檔化
@Inherited
註解是自動繼承的,想讓一個類和它的子類都包含某個註解,就可以使用它來修飾註解
@Target
Target通過ElementType來指定註解可使用範圍的枚舉集合
ElementType的用法
取值 | 註解使用範圍 |
---|---|
METHOD | 可用於方法上 |
TYPE | 可用於類、接口、註解類型或枚舉類型 |
ANNOTATION_TYPE | 可用於註解類型上(被@interface修飾的類型) |
CONSTRUCTOR | 可用於構造方法上 |
FIELD | 可用於域上 |
LOCAL_VARIABLE | 可用於局部變量上 |
PACKAGE | 用於記錄java文件的package信息 |
PARAMETER | 可用於參數上 |
3. 自定義註解例子:
使用@interface自定義註解時,自動繼承了java.lang.annotation.Annotation接口,由編譯程序自動完成其他細節。在定義註解時,不能繼承其他的註解或接口。@interface用來聲明一個註解,其中的每一個方法實際上是聲明瞭一個配置參數。方法的名稱就是參數的名稱,返回值類型就是參數的類型(返回值類型只能是基本類型、Class、String、enum)。可以通過default來聲明參數的默認值。
自定義註解格式:
public @interface 註解名{註解體}
1.所有基本數據類型(int,float,boolean,byte,double,char,long,short)
2.String類型
3.Class類型
4.enum類型
5.Annotation類型
6.以上所有類型的數組
Annotation類型裏面的參數該怎麼設定:
第一,只能用public或默認(default)這兩個訪問權修飾.例如,String value();這裏把方法設爲defaul默認類型;
第二,參數成員只能用基本類型byte,short,char,int,long,float,double,boolean八種基本數據類型和 String,Enum,Class,annotations等數據類型,以及這一些類型的數組.例如,String value();這裏的參數成員就爲String;
第三,如果只有一個參數成員,最好把參數名稱設爲"value",後加小括號.例:下面的例子Name註解就只有一個參數成員。
註解元素的默認值
註解元素注意點:
註解元素必須有確定的值,要麼在定義註解的默認值中指定,要麼在使用註解時指定,非基本類型的註解元素的值不可爲null。因此, 使用空字符串或0作爲默認值是一種常用的做法。這個約束使得處理器很難表現一個元素的存在或缺失的狀態,因爲每個註解的聲明中,所有元素都存在,並且都具有相應的值,爲了繞開這個約束,我們只能定義一些特殊的值,例如空字符串或者負數,一次表示某個元素不存在,在定義註解時,這已經成爲一個習慣
1.Name.java(姓名註解)
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
*
* @description:姓名註解
* @author: libl
* @date: 2018年5月12日
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Name {
String value() default "";
}
2.Gender.java(性別註解)
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @description:性別註解
* @author: libl
* @date: 2018年5月12日
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Gender {
public enum GenderType {
Male("男"), Female("女"), Other("中性");
private String genderStr;
private GenderType(String arg0) {
this.genderStr = arg0;
}
@Override
public String toString() {
return genderStr;
}
}
GenderType gender() default GenderType.Male;
}
3.Profile.java(基本資料註解)
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
*
* @description:基本資料註解
* @author: libl
* @date: 2018年5月12日
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Profile {
/**
* ID
*
* @return
*/
public int id() default -1;
/**
* 身高
*
* @return
*/
public int height() default 0;
/**
* 籍貫
*
* @return
*/
public String nativePlace() default "";
}
4.Person.java(使用註解)
/**
*
* @description:使用自定義註解
* @author: libl
* @date: 2018年5月12日
*/
public class Person {
@Name("李保磊")
private String name;
@Gender(gender = Gender.GenderType.Male)
private String gender;
@Profile(id = 1001, height = 180, nativePlace = "CN")
private String profile;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public String getProfile() {
return profile;
}
public void setProfile(String profile) {
this.profile = profile;
}
}
接口提供了以下四個方法來訪問Annotation的信息:
方法1:< T extends Annotation > T getAnnotation(Class< T > annotationClass): 返回改程序元素上存在的、指定類型的註解,如果該類型註解不存在,則返回null。
方法2:Annotation[] getAnnotations():返回該程序元素上存在的所有註解。
方法3:boolean isAnnotationPresent(Class<? extends Annotation> annotationClass):判斷該程序元素上是否包含指定類型的註解,存在則返回true,否則返回false.
方法4:Annotation[] getDeclaredAnnotations():返回直接存在於此元素上的所有註釋。與此接口中的其他方法不同,該方法將忽略繼承的註釋。(如果沒有註釋直接存在於此元素上,則返回長度爲零的一個數組。)該方法的調用者可以隨意修改返回的數組;這不會對其他調用者返回的數組產生任何影響。
5.TestUtils.java(測試註解)
import java.lang.reflect.Field;
/**
*
* @description:註解測試
* @author: libl
* @date: 2018年5月12日
*/
public class TestUtils {
public static void main(String[] args) {
TestUtils.getInfo(Person.class);
}
public static void getInfo(Class<?> clazz) {
String name = "";
String gender = "";
String profile = "";
Field fields[] = clazz.getDeclaredFields();
for (Field field : fields) {
if (field.isAnnotationPresent(Name.class)) {
Name arg0 = field.getAnnotation(Name.class);
name = name + arg0.value();
System.out.println("name=" + name);
}
if (field.isAnnotationPresent(Gender.class)) {
Gender arg0 = field.getAnnotation(Gender.class);
gender = gender + arg0.gender().toString();
System.out.println("gender=" + gender);
}
if (field.isAnnotationPresent(Profile.class)) {
Profile arg0 = field.getAnnotation(Profile.class);
profile = "[id=" + arg0.id() + ",height=" + arg0.height() + ",nativePlace=" + arg0.nativePlace() + "]";
System.out.println("profile=" + profile);
}
}
}
}
運行結果: