注解其实就是代码里的特殊标记,必须搭配注解的信息处理流程才有意义(使用反射)。
这些标记可以在编译、类加载、运行时被读取,并执行相应的处理。
注解可以修饰:包、类、构造器、成员变量、方法、参数、局部变量 的声明。
这些信息被保存在注解的 “name=value” 对中。
常用的注解
生成文档相关的注解
@author:标明开发该类模块的作者,多个作者之间使用 ,分割
@version:标明该类模块的版本
@see:参考转向,也就是相关主题
@since:从哪个版本开始增加的
@param:对方法中参数的说明
@return:对方法返回值的说明
@exception:对方法可能抛出的异常进行说明
其中 @param @return @exception 这三个注解只能用于方法
在编译时进行格式检查的注解 也是 JDK 内置的三个注解
@Override:只用于重写父类方法
@Deprecated:用于表示所修饰的元素(类,方法、属性)已过时,不建议使用,但是还能调用
@SuppressWarnings:抑制编译器警告
@Testpublic void Test() {// 如果 a 没有被使用,则会有一个警告,但不影响运行// 如果 a 没有被使用,加上该注解后,警告消失@SuppressWarnings("unused")int a = 10;}
自定义注解
JDK 中的元注解
@Target:用于指定修饰元素的类型(类、构造器、局部变量 等)
@Retention:用于指定注解的生命周期
- source:编译后,注解将会被丢弃,即 class 文件中无该注解
- class:编译后,注解将被保留在 class 文件中,但运行 Java 程序时,JVM 不保留注解
- runtime:编译后,注解将被保留在 class 文件中,并且运行 Java 程序时,JVM 保留注解
- 如果不写,class 属性是生命周期的默认值
@Document:默认情况,JavaDoc 不包含注解,如果注解被 @Document 修饰,则注解被 JavaDoc 提取成文档
@Inherited:被 @Inherited 修饰的注解具有继承性。默认不具有继承性。
元注解用于修饰其他注解。
注解用 @interface 声明。
注解 默认继承 java.lang.annotation.Annotation 接口。
注解的成员变量,以无参方法的形式声明。
如果成员变量只有一个 value 变量,则使用时,value 可省略不写。
可以用 default 关键字为注解的成员变量指定初始值。
public @interface LoginRequired {boolean value() default true;}
Java8 对元注解的增强
可重复注解
可重复注解,即注解可以重复定义多个。
两个注解的 Target、Retention、Inherited 等元注解 必须相同
@MyAnnotation(value="hi")@MyAnnotation(value="abc")class Person{private String name;private int age;public Person() {}}@Repeatable(MyAnnotations.class)@Retention(RetentionPolicy.RUNTIME)@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})public @interface MyAnnotation {String value();}@Retention(RetentionPolicy.RUNTIME)@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})public @interface MyAnnotations {MyAnnotation[] value();}
在 JDK8 之前,注解只能在声明上使用,
在 JDK8 及之后,注解可以写在任何使用类型的地方。
JDK8 的元注解 @Target 的参数类型 ElementType 枚举值多了两个:TYPE_PARAMETER、TYPE_USE
@Target(value = {ElementType.TYPE_PARAMETER})@Retention(RetentionPolicy.RUNTIME)@interface Ann7 {String value() default "";}public class UseAnnotation7<@Ann7() T0, @Ann7() T1> {public <@Ann7() T2> void m1() {}public static void main(String[] args) throws NoSuchMethodException {for (TypeVariable typeVariable : UseAnnotation7.class.getTypeParameters()) {print(typeVariable);}for (TypeVariable typeVariable : UseAnnotation7.class.getDeclaredMethod("m1").getTypeParameters()) {print(typeVariable);}}private static void print(TypeVariable typeVariable) {System.out.println("类型变量名称:" + typeVariable.getName());Arrays.stream(typeVariable.getAnnotations()).forEach(System.out::println);}}类型变量名称:T0@com.javacode2018.lesson001.demo18.Ann7(value="")类型变量名称:T1@com.javacode2018.lesson001.demo18.Ann7(value="")类型变量名称:T2@com.javacode2018.lesson001.demo18.Ann7(value="")
public enum ElementType {/* 类、接口、枚举、注解上面 */TYPE,/* 字段上 */FIELD,/* 方法上 */METHOD,/* 方法的入参上 */PARAMETER,/* 构造函数上 */CONSTRUCTOR,/* 局部变量上 */LOCAL_VARIABLE,/* 注解上 */ANNOTATION_TYPE,/* 包上 */PACKAGE,/* 类型参数上(类型变量) */TYPE_PARAMETER,/* 类型名称上,即任何使用类型的地方 */TYPE_USE}
