目录
一、元注解
定义:修饰注解的注解叫做元注解
@Target
指定注解的使用范围,不写默认可使用在任何地方(除了自定义类型声明语句、成员变量上的泛型,需指定ElementType.TYPE_PARAMETER、ElementType.TYPE_USE)
可通过ElementType来限制注解的使用范围
public enum ElementType {
/* 类、接口(包括注解类型)或枚举声明 */
TYPE,
/* 字段声明(包括enum常量) 就是成员变量 */
FIELD,
/* 方法声明 */
METHOD,
/* 正式的参数声明 */
PARAMETER,
/* 构造函数声明 */
CONSTRUCTOR,
/* 局部变量声明 */
LOCAL_VARIABLE,
/* 注解类型声明 */
ANNOTATION_TYPE,
/* 包声明 */
PACKAGE,
/* 类型参数声明 jdk1.8及以后 */
TYPE_PARAMETER,
/** 类型的使用 jdk1.8及以后 */
TYPE_USE
}
TYPE_PARAMETER:可以使用在自定义类型参数(可以是javaBean或者枚举等)的声明语句中
若想在类声明语句中的泛型上调用注解,得加上TYPE_PARAMETER
TYPE_USE:表示该注解能使用在使用类型的任意语句中。
- 创建实例时使用
User user1 = new @Annotation1 User();
- 类型强转时使用
Object o = "1";
String s = (@Annotation1 String) o;
- 方法形参时使用
public void Test(@Annotation1("方法参数上的注解") String s, @Annotation1("方法参数上的注解2") String s2){
}
- 泛型中使用
private Map<@Annotation1("成员变量泛型上的注解") String,String> map;
参考:JAVA8新特性--类型注解与重复注解_凶猛的小蜜蜂-CSDN博客_type_use
@Documented
在声明注解时指定 @Documented,则它会被 javadoc 之类的工具处理, 注解类型信息也会被包括在生成的文档中。
@Inherited
JDK中定义注解不可继承,使用该注解可被继承
作用:让子类可以继承修饰父类的注解,前提是此注解已被@Inherited修饰。
@Inherited使得被其修饰的注解能够被继承。
扩展:在spring中也有一个@AliasFor注解可实现注解继承效果,不过得通过spring处理后才能实现功能
@Retention
注解的保留策略(枚举类RetentionPolicy),RetentionPolicy可选值:
SOURCE:注解仅存在于源码中,在class字节码文件中不包含
CLASS:默认的保留策略,注解在class字节码文件中存在,但运行时无法获得
RUNTIME:注解在class字节码文件中存在,在运行时可以通过反射获取到
二、自定义注解
jdk中和注解有关的类都定义在java.lang.annotation包中
注解的本质还是接口,注解继承了Annotation接口
注解使用@interface来定义
例如:定义一个TestAnnotation注解
public @interface TestAnnotation {
int age() default 1;
}
注意:1.访问修饰符必须是public 不写默认public
2.参数类型必须是基本数据类型、String、Class、枚举类型、注解类型以及上述类型的数组,像Integer、Double这些(包装类型)都不行。
3.参数名字一般定义为名词,如果只有一个参数,一般定义为value。
因为:只有一个参数,并且名称为value时,注解使用时可以省略参数名。
即:
public @interface TestAnnotation {
String value();
}
这时可以直接写
@TestAnnotation("1")
4.default设定参数默认值,使用注解时不指定参数,参数使用默认值。
5.参数名称后面的()内不能添加任何东西,这只是个特殊的语法。
6.如果没有默认值,使用注解时必须赋值
三、注解信息的获取
Java在 java.lang.reflect 反射包下增设了AnnotatedElement 接口
主要用于表示目前正在虚拟机中运行的程序中已使用注解的元素,通过该接口提供的方法可以利用反射技术读取注解的信息
Package:用来表示包的信息
Class:用来表示类的信息
Constructor:用来表示构造方法信息
Field:用来表示类中属性信息
Method:用来表示方法信息
Parameter:用来表示方法参数信息
以上这些类实现了AnnotatedElement接口
@Target({ElementType.TYPE,
ElementType.METHOD,
ElementType.FIELD,
ElementType.TYPE_USE,
ElementType.PARAMETER,
ElementType.CONSTRUCTOR})
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface Annotation1 {
String value() default "";
}
@Annotation1("类上的注解")
public class TestAnnotation <@Annotation1("类变量类型(泛型)上的注解") T0,T1>{
@Annotation1("成员变量上的注解")
private Map<@Annotation1("成员变量泛型上的注解") String,String> map;
@Annotation1("成员方法上的注解")
public void Test(@Annotation1("方法参数上的注解") String s, @Annotation1("方法参数上的注解2") String s2){
}
@Annotation1("构造函数上的注解")
public TestAnnotation(){
}
}
@Test
public void test12() throws NoSuchFieldException, NoSuchMethodException {
Class<TestAnnotation> clazz = TestAnnotation.class;
//获取类上的注解
Annotation[] annotations = clazz.getAnnotations();
for(Annotation annotation : annotations){
System.out.println(annotation);
}
//是否存在注解
/*if(clazz.isAnnotationPresent(Annotation1.class)){
Annotation1 annotation1 = clazz.getAnnotation(Annotation1.class);
System.out.println(annotation1.value());
}*/
//获取类的类型变量(泛型)的注解
TypeVariable<Class<TestAnnotation>>[] typeParameters = clazz.getTypeParameters();
for(TypeVariable typeVariable : typeParameters){
System.out.println(typeVariable.getName());
Annotation[] annotations1 = typeVariable.getAnnotations();
for (Annotation annotation : annotations1) {
System.out.println(annotation);
}
}
//获取成员变量上的注解
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
System.out.println(field.getName());
for (Annotation annotation : field.getAnnotations()) {
System.out.println(annotation);
}
}
//获取成员变量泛型的注解
for (Field field : fields) {
AnnotatedParameterizedType annotatedType = (AnnotatedParameterizedType) field.getAnnotatedType();
AnnotatedType[] typeArguments = annotatedType.getAnnotatedActualTypeArguments();
for (AnnotatedType typeArgument : typeArguments) {
for (Annotation annotation : typeArgument.getAnnotations()) {
System.out.println(annotation);
}
}
}
//获取成员方法上的注解
Method test = clazz.getMethod("Test", String.class, String.class);
for (Annotation annotation : test.getAnnotations()) {
System.out.println(annotation);
}
//获取成员方法上的参数注解
for (Parameter parameter : test.getParameters()) {
for (Annotation annotation : parameter.getAnnotations()) {
System.out.println(annotation);
}
}
//获取构造函数上的注解
Constructor<TestAnnotation> constructor = clazz.getConstructor();
for (Annotation annotation : constructor.getAnnotations()) {
System.out.println(annotation);
}
}
参考地址:JAVA核心知识点--元注解详解_pengjunlee的博客-CSDN博客_元注解
java学习-自定义注解,使用注解,注解的信息获取,注解继承_whatname123的博客-CSDN博客_自定义注解继承