注解概述
●就是Java代码里的特殊标记,比如:@Override、@Test等,作用是:让其他程序根据注解信息来决定怎么执行该程序。
●注意:注解可以用在类上、构造器上、方法上、成员变量上、参数上、等位置处。
注解概述-注解的原理
注解本质是一个接口,Java中所有注解都是继承了Annotation接口的。
@注解(…):其实就是一个实现类对象,实现了该注解以及Annotation接口。
注解:自定义注解
介绍
自定义注解:就是自己定义注解。
格式:
public @interface 注解名称 {
public 属性类型 属性名() default 默认值 ;
}
@interface 就是 Java 中定义自定义注解(Annotation)的专属关键字—— 它的唯一用途就是声明一个注解类型,明确告诉编译器 “这是一个用于存储元数据的注解”,是自定义注解的 “标识性语法”。
注解接口中的成员方法默认就是 public 的,可以省略不写。
特殊属性名:value
如果注解中只有一个 value(特殊属性名)属性,使用注解时,value名称可以不写!!
此外注解中存在多个属性设置了默认值,并且只有当注解中所有未指定默认值的属性 “仅有 value(特殊属性名) 一个” 时,使用注解时,才能省略 value(特殊属性名)属性名称。
public @interface A{
// 方式1:带默认值
String name() default "";//可选属性,已经设置了默认值
// 当前代码(可以工作但不推荐)
//char name2() default 2;//整数字面量 2 会被自动转换为 char 类型,相当于 (char) 2,即隐式类型转换
//char name3() default '';//报错,字符一定要有一个字符并且只能有一个
// 推荐写法
//char name4() default '2';
// 方式2:不带默认值(使用时必须指定)
int age();//必选属性,未设置默认值
// 方式3:使用value作为特殊名称(可省略名称)
char value() default 'w';//可选属性,已经设置了默认值
}
必需属性:没有默认值的属性(如 age( ))- 必须在使用注解时指定
可选属性:有默认值的属性(如 name( )default " ")- 可以省略不写
@A(name = "",age = 22,value = 'w')
// 以上代码可以省略成以下代码
@A(age = 22)//可选属性name和value的属性值可以省略
// value(特殊属性名)简化赋值(多元素)
@MyAnnotation({"/a", "/b"}) // 等价于 value = {"/a", "/b"}
// 简化赋值(单元素)
@MyAnnotation("/a") // 等价于 value = {"/a"}
// 如果将int age();修改为int age() default 20;
// 同时将char value() default 'w';修改为char value();
// 满足多个属性有默认值,有却仅有一个value(特殊属性名)
// 注解就可以只写值不写名称
@A(22)
Java注解中可以定义的成员变量类型
- 基本数据类型
public @interface MyAnnotation {
byte byteValue() default 0;
short shortValue() default 0;
int intValue() default 0;
long longValue() default 0L;
float floatValue() default 0.0f;
double doubleValue() default 0.0;
boolean booleanValue() default false;
char charValue() default '\0';
}
2. 字符串类型
public @interface MyAnnotation {
String value() default "";
String name() default "default";
}
3. Class类型
public @interface MyAnnotation {
Class<?> clazz() default Object.class;
Class<? extends List> listType() default ArrayList.class;
}
- 枚举类型
enum Status { ACTIVE, INACTIVE }
public @interface MyAnnotation {
Status status() default Status.ACTIVE;
}
- 注解类型
public @interface NestedAnnotation {
String value() default "";
}
public @interface MyAnnotation {
NestedAnnotation nested() default @NestedAnnotation("");
}
- 数组类型
public @interface MyAnnotation {
String[] names() default {};
//String[] name() default null; // 注解属性不能设为null
int[] values() default {1, 2, 3};
Class<?>[] classes() default {Object.class};
}
数组类型的赋值简化:当数组中只有一个元素时,可省略{},直接写单个值。
@MyAnnotation(names = "张三") // 合法,等同于 names = {"张三"}
@MyAnnotation(names = {"张三", "李四"}) // 多元素需用{}
7. 重要限制
成员变量不能是 null
成员变量不能是任意对象实例
成员变量必须在编译时就能确定值,同时注解属性的 “默认值必须是编译期常量”
不支持 void 类型
不支持复杂对象类型(除非是上述允许的类型)
注解:元注解
介绍
元注解:指的是:描述注解的注解。
//例如 : @Test上的注解
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface Test {
}
常用注解
@Target
作用:声明被修饰的注解只能在哪些位置使用
@Target 注解是一个数组,可以为一个或多个目标元素类型同时指定注解的使用范围。
@Target(ElementType.TYPE) | |@Target({ElementType.TYPE,ElementType.METHOD})
1TYPE,类、接口(包括注解类型)、枚举类
2.FIELD,成员变量
3.METHOD,成员方法
4.PARAMETER,方法参数
5.CONSTRUCTOR,构造器
6LOCAL_VARIABLE,局部变量
@Retention
作用:声明注解的保留周期
@Retention(RetentionPolicy.RUNTIME)
1.SOURCE
只作用在源码阶段,字节码文件中不存在
2.CLASS(默认值)
保留到字节码文件阶段,运行阶段不存在
3.RUNTIME(开发常用)AnnotatedElement接口提供了解析注解的方法说明public Annotation[] getDeclaredAnnotations()获取当前对象上面的注解。public T getDeclaredAnnotation(Class annotationClass)获取指定的注解对象public boolean isAnnotationPresent(Class annotationClass)判断当前对象上是否存在某个注解
一直保留到运行阶段
注解的解析
就是判断类上、方法上、成员变量上是否存在注解,并把注解里的内容给解析出来。
如何解析注解?
指导思想:要解析谁上面的注解,就应该先拿到谁。
比如要解析类上面的注解,则应该先获取该类的Class对象,再通过Class对象解析其上面的注解。
比如要解析成员方法上的注解,则应该获取到该成员方法的Method对象,再通过Method对象解析其上面的注解。
Class 、Method 、Field ,Constructor、都实现了AnnotatedElement接口,它们都拥有解析注解的能力。
注解解析的前提条件:
- 只有当注解的
@Retention设置为RetentionPolicy.RUNTIME时,才能在运行时通过反射解析注解! - 若
@Retention是SOURCE(源码阶段)或CLASS(字节码阶段),运行时getDeclaredAnnotations()会返回空数组,无法获取注解信息。
| AnnotatedElement接口提供了解析注解的方法 | 说明 |
|---|---|
| public Annotation[] getDeclaredAnnotations() | 获取当前对象上面的注解 |
| public T getDeclaredAnnotation(Class annotationClass) | 获取指定的注解对象 |
| public boolean isAnnotationPresent(Class annotationClass) | 判断当前对象上是否存在某个注解 |