放在被定义的一个注解类的前面,是对注解的一种限制。
@Retention:用来说明该注解类的生命周期。可选参数:
RetentionPolicy.SOURCE:注解只保留在源文件中
RetentionPolicy.CLASS:注解保留在class文件中,在加载到JVM虚拟机时丢弃
RetentionPolicy.RUNTIME:注解保留在程序运行期间,此时可以通过反射获得定义在某个类上的所有注解
@Target:用于描述注解的使用范围。可选参数:
ElementType.TYPE:说明该注解只能被声明在一个类前。
ElementType.FIELD:说明该注解只能被声明在一个类的字段前。
ElementType.METHOD:说明该注解只能被声明在一个类的方法前。
ElementType.PARAMETER:说明该注解只能被声明在一个方法参数前。
ElementType.CONSTRUCTOR:说明该注解只能声明在一个类的构造方法前。
ElementType.LOCAL_VARIABLE:说明该注解只能声明在一个局部变量前。
ElementType.ANNOTATION_TYPE:说明该注解只能声明在一个注解类型前。
ElementType.PACKAGE:说明该注解只能声明在一个包名前。
@Documented:
@Documented是一个标记注解,没有成员。@Documented 注解表明这个注解应该被 javadoc工具记录. 默认情况下,javadoc是不包括注解的. 但如果声明注解时指定了 @Documented,则它会被 javadoc 之类的工具处理, 所以注解类型信息也会被包括在生成的文档中。
@Inherited:
@Inherited 元注解是一个标记注解,@Inherited表示这个注解可以继承超类注解。即子类可以获取父类的注解信息。
注意:该注解只能用来声明类。不能用于接口
二、自定义注解
使用@interface自定义注解时,自动继承了java.lang.annotation.Annotation接口,由编译程序自动完成其他细节。在定义注解时,不能继承其他的注解或接口。@interface用来声明一个注解,其中的每一个方法实际上是声明了一个配置参数。方法的名称就是参数的名称,返回值类型就是参数的类型(返回值类型只能是基本类型、Class、String、enum)。可以通过default来声明参数的默认值。
定义注解格式:
public @interface 注解名 {定义体}
注解参数设定:
(1)注解类型的参数设定只能用public或默认(default)这两个访问修饰。
(2)参数支持数据类型
1.所有基本数据类型(int,float,boolean,byte,double,char,long,short)
2.String类型
3.Class类型
4.enum类型
5.Annotation类型
6.以上所有类型的数组
注解参数默认值:
注解元素必须有确定的值,要么在定义注解的默认值中指定,要么在使用注解时指定,非基本类型的注解元素的值不可为null。因此, 使用空字符串或0作为默认值是一种常用的做法。
三、读取注解
Java使用Annotation接口来代表程序元素前面的注解,该接口是所有Annotation类型的父接口。除此之外,Java在java.lang.reflect 包下新增了AnnotatedElement接口,该接口代表程序中可以接受注解的程序元素,该接口主要有如下几个实现类:
Class:类定义
Constructor:构造器定义
Field:类的成员变量定义
Method:类的方法定义
Package:类的包定义
java.lang.reflect 包下主要包含一些实现反射功能的工具类,实际上,java.lang.reflect 包所有提供的反射API扩充了读取运行时Annotation信息的能力。当一个Annotation类型被定义为运行时的Annotation后,该注解才能是运行时可见,当class文件被装载时被保存在class文件中的Annotation才会被虚拟机读取。
AnnotatedElement 接口是所有程序元素(Class、Method和Constructor)的父接口,所以程序通过反射获取了某个类的AnnotatedElement对象之后,程序就可以调用该对象的如下四个个方法来访问Annotation信息:
方法1:<T extends Annotation> T getAnnotation(Class<T> annotationClass): 返回改程序元素上存在的、指定类型的注解,如果该类型注解不存在,则返回null。
方法2:Annotation[] getAnnotations():返回该程序元素上存在的所有注解。
方法3:boolean is AnnotationPresent(Class<?extends Annotation> annotationClass):判断该程序元素上是否包含指定类型的注解,存在则返回true,否则返回false.
方法4:Annotation[] getDeclaredAnnotations():返回直接存在于此元素上的所有注解。与此接口中的其他方法不同,该方法将忽略继承的注释。(如果没有注释直接存在于此元素上,则返回长度为零的一个数组。)该方法的调用者可以随意修改返回的数组;这不会对其他调用者返回的数组产生任何影响。
四、示例
示例一:
定义注解:
package com.learn.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface InformationAnnotation {
String school() default "CPU";
public String city() default "江苏";
}
使用类:
package com.learn.annotation;
@InformationAnnotation(school="NJAU")
public class Student {
}
调用类:
package com.learn.annotation;
public class Test {
public static void main(String[] args) {
InformationAnnotation information = Student.class.getAnnotation(InformationAnnotation.class);
//输出赋予的值
System.out.println(information.school());
//输出默认值
System.out.println(information.city());
}
}
结果:
NJAU
江苏
示例二:子类继承了父类的注解,获取到父类的注解参数值
定义注解
package com.learn.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface InformationAnnotation {
public String school() default "CPU";
public String city() default "江苏";
}
使用父类:
package com.learn.annotation;
@InformationAnnotation(city="上海")
public class Parent {
public void doSomething()
{
System.out.println("do some thing");
}
}
子类:
package com.learn.annotation;
public class Son extends Parent{
}
测试类:
package com.learn.annotation;
public class Test {
public static void main(String[] args) {
InformationAnnotation information = Son.class.getAnnotation(InformationAnnotation.class);
//输出赋予的值
System.out.println(information.school());
//输出默认值
System.out.println(information.city());
}
}
结果:
CPU
上海