Java注解是附加在代码中的一些元信息,用于一些工具在编译、运行时进行解析和使用,起到说明、配置的功能,注解相关类都包含在java.lang.annotation包中。
Java注解分类
JDK基本注解
JDK元注解
自定义注解
JDK基本注解
@Override
重写
@SuppressWarnings(value = "unchecked")
压制编辑器警告
元注解
元注解的作用就是负责注解其他注解,元注解有以下6种
- @Target:用来限制注解的使用范围
- @Retention:指定其所修饰的注解的保留策略
- @Document:该注解是一个标记注解,用于指示一个注解将被文档化
- @Inherited:该注解使父类的注解能被其子类继承
- @Repeatable:该注解是Java8新增的注解,用于开发重复注解
- 类型注解(Type Annotation):该注解是Java8新增的注解,可以用在任何用到类型的地方
重点:一定要记住 @Target、@Retention 这两个元注解!
@Target
@Target注解用来限制注解的使用范围,即指定被修饰的注解能用于哪些程序单元
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
/**
* Returns an array of the kinds of elements an annotation type
* can be applied to.
* @return an array of the kinds of elements an annotation type
* can be applied to
*/
ElementType[] value();
}
@Target({应用类型1, 应用类型2,...})
枚举类 ElementType.java 大致有以下几种枚举值
枚举值 | 功能描述 |
---|---|
ElementType.Type | 可以修饰类、接口、注解或枚举类型 |
ElementType.FIELD | 可以修饰属性(成员变量),包括枚举常量 |
ElementType.METHOD | 可以修饰方法 |
ElementType.PAPAMETER | 可以修饰参数 |
ElementType.CONSTRUCTOR | 可以修饰构造方法 |
ElementType.LOCAL_VARIABLE | 可以修饰局部变量 |
ElementType.ANNOTATION_TYPE | 可以修饰注解类 |
ElementType.PACKAGE | 可以修饰包 |
ElementType.TYPE_PARAMETER (Java8新增) | 表示该注解能写在类型变量的声明语句中,如:泛型 |
ElementType.TYPE_USE (Java8新增) | 表示该注解能写在使用类型的任何语句中 |
【示例】指定注解只能修饰类和方法
@Target({ElementType.TYPE, ElementType.METHOD})
//定义注解
@Retention
注解的保留策略,@Retention应用到一个注解上用于说明该注解的生命周期
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
/**
* Returns the retention policy.
* @return the retention policy
*/
RetentionPolicy value();
}
枚举类 RetentionPolicy.java 大致有以下三种枚举值:
- RetentionPolicy.SOURCE:注解只保留在源文件,当Java文件编译成class文件的时候,注解被遗弃。
- RetentionPolicy.CLASS:注解被保留到class文件,但jvm加载class文件时候被遗弃,这是默认的生命周期。
- RetentionPolicy.RUNTIME:注解不仅被保存到class文件中,jvm加载class文件之后,仍然存在,它可以保留到程序运行的时候,且会被加载进入到JVM中,所以在程序运行时可以获取到它们。
【示例】运行时JVM可以获取注解信息
@Retention(RetentionPolicy.RUNTIME)
//定义注解
@Documented
@Documented注解用于指定被修饰的注解可以被 javadoc 工具提取成文档。定义注解类时使用。
使用javadoc工具可以从程序源代码中抽取类、方法、成员等注释形成一个源代码配套的API帮助文档,而该工具抽取时默认不包括注释内容。@Documented注解进行修饰,则所有使用该注解修饰的程序元素的API文档中将会包含该注解说明。定义为@Documented的注解必须设置Retention值为RUNTIME。
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Documented {}
@Inherited
JDK中定义注解不可继承,如果某个注解使用@Inherited进行修饰,则该类使用该注解时,其子类将自动被修饰
@Inherited修饰的注解在父类中使用,假设子类没有使用任何注解,子类将继承父类的注解(继承@Inherited修饰的注解)
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Inherited {}
扩展:在spring中也有一个@AliasFor注解可实现注解继承效果,但是需要通过spring处理后才能实现功能
【示例】
@Retention(RetentionPolicy.RUNTIME) //表示下面的注解在运行时有效
@Documented //表示下面的注解信息可以被javadoc工具提取到API文档中
@Target(ElementType.TYPE) //表示下面的注解只可以修饰类
@Inherited //表示下面的注解所修饰的类中的注解使用可以被子类继承
public @interface MyAnnotation {
public String value() default "默认值";
public String value1() default "默认值";
}
@Repeatable
@Repeatable注解是Java8新增的注解,用于开发重复注解。在Java8之前,同一个程序元素前只能使用一个相同类型的注解,如果需要在同一个元素前使用多个相同类型的注解必须通过注解容器来实现。从Java8开始,允许使用多个相同的类型注解来修饰同一个元素,前提是该类型的注解是可重复的,即在定义注解时要用 @Repeatable元注解进行修饰。
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Repeatable {
/**
* Indicates the <em>containing annotation type</em> for the
* repeatable annotation type.
* @return the containing annotation type
*/
Class<? extends Annotation> value();
}
假设要重复使用同一个注解,在java8以前是这样做的
利用数组的形式,把相同的注解放在一维数组中
public @interface ManTypes {
ManType[] value();
}
@ManTypes({@ManType(value = "职工"),@ManType(value = "超人")})
public class Man {
}
使用@Repeatbla可以直接重复使用@ManType注解,不需要放在一维数组中,@Repeatble注解的value值需要填入class,这个注解本来是不能实现多次描述的它是依赖于@ManTypes这个注解,拿过来.class就可以了。
@Repeatable(value = ManTypes.class)
public @interface ManType {
public String value() default "";
}
@ManType(value = "职工")
@ManType(value = "超人")
public class Man {}
类型注解
Java8为ElementType枚举增加了TYPE_PARAMETER和TYPE_USE两个枚举类值,允许在定义枚举类时使用@Target(ElementType.TYPE_USE)来修饰,此种注解被称为“类型注解”(Type Annotation)。
在Java8之前,只能在定义类、接口、方法和成员变量等程序元素时使用注解,从Java8开始新增的类型注解可以用在任何用到类型的地方。
除了在定义类、接口和方法等常见的程序元素时可以使用类型注解,还可以在以下几个位置使用类型注解进行修饰:
- 创建对象(使用new关键字创建)
- 类型转换
- 使用implements实现接口
- 使用throws声明抛出异常序列
- 方法参数
自定义注解
jdk中和注解有关的类都定义在java.lang.annotation包中
注解本质上就是一个接口,该接口默认继承Annotation接口
注解使用@interface来定义,例如:定义一个TestAnnotation注解
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface TestAnnotation {
int age() default 1;
}
注意:
- 访问修饰符必须是public 不写默认public
- 参数类型必须是基本数据类型、String、Class、枚举类型、注解类型以及上述类型的数组,像Integer、Double这些(包装类型)都不行。
- 参数名字一般定义为名词,如果只有一个参数,一般定义为value。