https://mp.weixin.qq.com/s/KXhaPeTwceX5dcmSQqMnMw
一 如何自定义
注解本质上就是一个接口,该接口默认继承Annotation接口。
public interface MyAnno extends java.lang.annotation.Annotation {}
- 定义一个注解
a.注解体(@interface)
b.注解变量(变量名后带一对括号;可以有默认值;返回类型是Java基本类型)
c.元注解(@Target、@Retention、@Documented、@Inherited) - 实现注解的操作——>通过反射获取对象
- 运用注解——>可以标注在类、方法、构造方法、成员变量等
1 注解体和注解变量
在Java中,类使用class定义,接口使用interface定义,注解和接口的定义差不多,增加了一个@符号,即@interface,代码如下:
public @interface EnableAuth {
}
注解中可以定义成员变量,用于信息的描述,跟接口中方法的定义类似,代码如下:
public @interface EnableAuth {
String name();
}
还可以添加默认值:
public @interface EnableAuth {
String name() default "默认值";
}
上面的介绍只是完成了自定义注解的第一步,开发中日常使用注解大部分是用在类上,方法上,字段上,示列代码如下:
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface EnableAuth {
}
2 元注解
- @Target
@Target注解用来限制注解的使用范围,即指定被修饰的注解能用于哪些程序单元
@Target({应用类型1, 应用类型2,...})
枚举值 | 功能描述 |
---|---|
ElementType.Type | 可以修饰类、接口、注解或枚举类型 |
ElementType.FIELD | 可以修饰属性(成员变量),包括枚举常量 |
ElementType.METHOD | 可以修饰方法 |
ElementType.PAPAMETER | |
可以修饰参数 | |
ElementType.CONSTRUCTOR | 可以修饰构造方法 |
ElementType.LOCAL_VARIABLE | 可以修饰局部变量 |
ElementType.ANNOTATION_TYPE | 可以修饰注解类 |
ElementType.PACKAGE | 可以修饰包 |
- Retention
@Retention(RetentionPolicy.RUNTIME)
@Retention注解用于指定被修饰的注解可以保留多长时间,即指定JVM策略在哪个时间点上删除当前注解。保留策略值有以下三个:
策略值 | 功能描述 |
---|---|
Retention.SOURCE | 注解只在源文件中保留,在编译期间删除 |
Retention.CLASS | 注解只在编译期间存在于.class文件中,运行时JVM不可获取注解信息,该略值也是默认值 |
Retention.RUNTIME | 运行时JVM可以获取注解信息(反射),是最长注解持续期 |
- @Documented
@Document
@Document注解用于指定被修饰的注解可以被javadoc工具提取成文档。定义注解类时使用该注解进行修饰,则所有使用该注解修饰的程序元素的API文档中将会包含该注解说明。
- Inherited
@Inherited注解指定注解具有继承性,如果某个注解使用@Inherited进行修饰,则该类使用该注解时,其子类将自动被修饰。如下:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface InheritedAnno1 {
String comment();
int order() default 1;
}
//使用自定义的@InheritedAnno1注解修饰Base
@InheritedAnno1(comment = "继承注解", order = 2)
class Base{
}
//InheritedDemo只继承了Base类
//并未直接使用@InheritedAnno1注解
public class InheritedDemo extends Base{
public static void main(String[] args) {
//从InheritedDemo中获取InheritedAnno1注解信息
InheritedAnno1 anno = InheritedDemo.class.getAnnotation(InheritedAnno1.class);
//输出InheritedAnno1注解成员信息
System.out.println(anno.comment()+":"+anno.order());
//打印InheritedDemo类是否具有@InheritedAnno1修饰
System.out.println(InheritedDemo.class.isAnnotationPresent(InheritedAnno1.class));
}
}
运行结果:
二 . 定义要求
1、属性的返回值类型有下列取值:
- 基本数据类型
- String
- 枚举
- 注解
- 以上类型的数组
2、定义了属性,在使用时需要给属性赋值
- 如果定义属性时,使用default关键字给属性默认初始化值,则使用注解时,可以不进行属性的赋值。
- 如果只有一个属性需要赋值,并且属性的名称是value,则value可以省略,直接定义值即可。
- 数组赋值时,值使用{}包裹。如果数组中只有一个值,则{}可以省略