Java注解用于提供程序信息,可以是给编译器的信息,也可以是编译时刻和部署时刻的处理,还可以是运行时刻的处理。注解是用“@”引导的标识,可以加在类、成员变量、方法、参数等元素声明的前面。注解类实际上是一种特殊的接口,默认继承了java.lang.annotation.Annotation接口。
Java内置注解
java.lang包中定义了3个注解:
@Deprecated:表明该元素已经过期,建议不使用。
@Override:表明该方法是重写基类的同名方法。
@Suppresswarning:表明忽略该元素可能发生的警告。
java.lang.annotation包中定义了4个注解用于编写注解类:
@Documented:表示将注解包含在Javadoc中。
@Inherited:表示该注解类具有继承性。该注解标注的类的子类也自动被该注解标注。
@Retention:表示该注解信息的保存策略。传入值为枚举类RetentionPolicy的值。
@Target:表示该注解可以标注的元素。传入值为枚举类ElementType的值。
java.lang.annotation包中定义了2个枚举类:
RetentionPolicy:保存策略。取值有:
CLASS:编译器把该注解记录在class文件中。当运行java程序时,JVM不可获取注解信息。默认值。
RUNTIME:编译器把该注解记录在class文件中。当运行java程序时,JVM可获取注解信息,程序可以通过反射获取该注解信息。
SOURCE:该注解只保存在源代码中,编译器直接丢弃该注解。
ElementType:注解标注位置。取值有:
ANNOTATION_TYPE:注解类。
CONSTRUCTOR:构造器。
FIELD:成员变量。
LOCAL_VARIABLE:局部变量。
METHOD:方法。
PACKAGE:包。
PARAMETER:方法参数。
TYPE:类、接口、枚举类。
自定义注解类
编写自定义注解类的步骤为:
1.使用“@interface”标识注解类。
2.定义注解属性:使用无参抽象方法来定义注解的属性,方法名为属性名,方法返回值类型为属性类型。属性类型可以为基本类型、String、Class、enum等以及对应的数组类型。
3.使用default来表明属性的默认值。没有默认值的属性在使用注解时必须给定属性的值。
4.注解类声明前面加上@Target注解表明可以标注的元素,加上@Retention注解表明保存策略。
以下是一个自定义注解类:
1 import java.lang.annotation.ElementType; 2 import java.lang.annotation.Inherited; 3 import java.lang.annotation.Retention; 4 import java.lang.annotation.RetentionPolicy; 5 import java.lang.annotation.Target; 6 7 @Target(ElementType.TYPE) // 标注在类声明上 8 @Retention(RetentionPolicy.RUNTIME) // JVM可以获得注解信息 9 @Inherited // 具有继承性 10 public @interface MyAnnotation { 11 12 // id:int类型,默认值为0 13 public int id() default 0; 14 15 // value:String类型,无默认值 16 public String value(); 17 18 }
该注解包含了两个属性:
id:int类型,默认值为0。使用该注解时可以不为该属性赋值,没有为该属性赋值时取默认值。
value:String类型,无默认值。使用该注解时必须为该属性赋值。
使用注解
使用注解的步骤为:
1.在合适位置标注注解。每个注解类都有使用@Target注解表明该注解可以标注的位置。
2.在注解后的“( )”里使用键值对为注解的属性赋值。如果赋值的属性只有一个,且属性名为value,则可以直接在“( )”中写入属性值,无需使用键值对。
以下是使用自定义注解类MyAnnotation的示例:
定义一个UseAnno类,使用@MyAnnotation注解标注该类。定义TestAnnotation类继承UseAnno类,使用反射获取标注TestAnnotation类的所有注解。
1 @MyAnnotation("val") 2 class UseAnno { 3 4 }
1 class TestAnnotation extends UseAnno { 2 3 @Test 4 void testAnnotation() { 5 Class<TestAnnotation> c = TestAnnotation.class; 6 for (Annotation a : c.getAnnotations()) 7 System.out.println(a); 8 } 9 10 }
输出结果:
TestAnnotation类没有使用@MyAnnotation注解标注,但是却可以获得该注解。这是因为TestAnnotation类继承了@MyAnnotation注解标注的UseAnno类,这就是注解的继承性,前提是注解类使用了@Inherited注解。
从输出的注解属性值可以看出,id=0是因为没有为id属性赋值,id属性取默认值,value="val"是因为@MyAnnotation("val")为value属性赋值为"val"。