1、概述
Java中提供了Annotation功能,该功能可用于类、构造方法、成员变量、方法、参数等的声明中。该功能并不影响程序的原型,但是会对编译器警告等辅助工具产生影响。
2、定义Annotation类型
a、在定义Annotation类型时,也需要用到用来定义接口的interface关键字,但需要在interface关键字前加一个“@”符号,即定义Annotation类型的关键字为@interface,这个关键字的隐含意思是继承了java.lang。annotation.Annotation接口。例如,下面的代码就定义了一个Annotation类型。
public @interface NoMemberAnnotation{
}
b、上面定义的Annotation类型@NoMemberAnnotation未包含任何成员,这样的Annotation类型被称为marker annotation。下面的代码定义了一个只包含一个成员的Annotation类型。
public @interface OneMemberAnnotation{
String value();
}
//String:成员类型。可用的成员类型有String、Class、primitive、enumerated和annotation,以及所列类型的数组。
//value:成员名称。如果在所定义的Annotation类型中只包含一个成员,通常将成员形成命名为value。
下面的代码定义了一个包含多个成员的Annotation类型。
public @interface MoreMemberAnnotation{
String describe();
Class type();
}
c、在为Annotation类型定义成员时,也可以为成员设置默认值。例如,下面的代码在定义Annotation类型是就为成员设置了默认值。
public @interface DefaultValueAnnotation{
String describe() default "<默认值>";
Class type() default void.class;
}
d、在定义Annotation类型是,还可以通过Annotation类型@Target来设置Annotation类型使用的程序元素种类。如果未设置@Target,则表示适用于所有程序元素。枚举类ElementType中的枚举常量用来设置@Targer,如下表所示。
枚举常量 | 说 明 |
ANNOTATION_TYPE | 表示用于Annotation类型 |
TYPE | 表示用于类、接口和枚举,以及Annotaion类型 |
CONSTRUCTOR | 表示用于构造方法 |
FIELD | 表示用于成员变量和枚举变量 |
METHOD | 表示用于方法 |
PARAMETER | 表示用于参数 |
LOCAL_VARIABLE | 表示用于局部变量 |
PACKAGE | 表示用于包 |
e、通过Annotation类型@Retention可以设置Annotation的有效范围。枚举类RetentionPolicy中的枚举常量用来设置@Retention,如下表所示。如果未设置@Retention,Annotation的有效范围为枚举常量CLASS表示的范围。
枚举常量 | 说 明 |
SOURCE | 表示不编译Annotation到类文件中,有效范围很小 |
CLASS | 表示编译Annotation到类文件中,但是在运行时不加载Annotation到JVM中 |
RUNTIME | 表示在运行时加载Annotation到JVM中,有效范围最大 |
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 package com.lzw; 2 3 import java.lang.annotation.*; 4 5 @Target(ElementType.CONSTRUCTOR) 6 // 用于构造方法 7 @Retention(RetentionPolicy.RUNTIME) 8 // 在运行时加载Annotation到JVM中 9 public @interface Constructor_Annotation { 10 String value() default "默认构造方法"; // 定义一个具有默认值的String型成员 11 }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import java.lang.annotation.*; 2 3 // 用于字段、方法和参数 4 @Target( { ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER }) 5 @Retention(RetentionPolicy.RUNTIME) 6 // 在运行时加载Annotation到JVM中 7 public @interface Field_Method_Parameter_Annotation { 8 String describe(); // 定义一个没有默认值的String型成员 9 10 Class type() default void.class; // 定义一个具有默认值的Class型成员 11 }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 package com.lzw; 2 3 public class Record { 4 @Field_Method_Parameter_Annotation(describe = "编号", type = int.class) 5 // 注释字段 6 int id; 7 @Field_Method_Parameter_Annotation(describe = "姓名", type = String.class) 8 String name; 9 10 @Constructor_Annotation() 11 // 采用默认值注释构造方法 12 public Record() { 13 } 14 15 @Constructor_Annotation("立即初始化构造方法") 16 // 注释构造方法 17 public Record( 18 @Field_Method_Parameter_Annotation(describe = "编号", 19 type = int.class) int id, 20 @Field_Method_Parameter_Annotation(describe = "姓名", 21 type = String.class) String name) { 22 this.id = id; 23 this.name = name; 24 } 25 26 @Field_Method_Parameter_Annotation(describe = "获得编号", type = int.class) 27 // 注释方法 28 public int getId() { 29 return id; 30 } 31 32 @Field_Method_Parameter_Annotation(describe = "设置编号") 33 // 成员type采用默认值注释方法 34 public void setId( 35 // 注释方法的参数 36 @Field_Method_Parameter_Annotation(describe = "编号", 37 type = int.class) int id) { 38 this.id = id; 39 } 40 41 @Field_Method_Parameter_Annotation(describe = "获得姓名", 42 type = String.class) 43 public String getName() { 44 return name; 45 } 46 47 @Field_Method_Parameter_Annotation(describe = "设置姓名") 48 public void setName( 49 @Field_Method_Parameter_Annotation(describe = "姓名", 50 type = String.class) String name) { 51 this.name = name; 52 } 53 }