注解巩固
本篇笔记用巩固Java注解基本概念,便于使用注解知识来学习如何编写框架。
注解概述
Annotaion
,注解是插入代码中的一种标记,在JDK1.5版本中引入。- Annotation 具备
类型-对象
的性质,可以存储数据(这类数据通常称为元数据,元数据就是数据中的数据)。 - 在编译和运行时期,我们可以对注解进行解析识别处理,用于达到功能解耦、代码跟踪(如:统计)、代码规范检查等目的。
- 编译时处理注解,使用预编译工具。
- 运行时处理注解,使用反射机制。
- 注解可以加在
类
、字段
、方法
和方法的参数
以及局部变量
上。
注解分类
Java内置注解
java.lang 包中的注解类型:
Deprecated
:过时,修饰已经过时的方法,成员,类。一般用此注解修饰的元素不推荐继续使用,避免风险。
Deprecated具有延续性,如果子类继承了被Deprecated标记的类并且复写了被标记为Deprecated的方法,在使用时则编译器不会提示子类方法过时警告,如果只是单纯继承了类,没有复写过时的方法,则编译器会提示方法过时警告。被标记的过时类会一直被提示警告。SupperessWarning
:压缩警告,通知编译器压制特定的编译警告。一般来说,警告分为2种性质,一种是error(不可忽略的,如try catch 缺少一个catch块),一种是warning(可压制的,如这个方法是过时的)。
@SupperessWarning 常见参数值:deprecation
:使用了不赞成使用的类或方法时的警告;
unchecked
:执行了未检查的转换时的警告,例如当使用集合时没有用泛型 (Generics) 来指定集合保存的类型;
fallthrough
:当 Switch 程序块直接通往下一种情况而没有 Break 时的警告;
path
:在类路径、源文件路径等中有不存在的路径时的警告;
serial
:当在可序列化的类上缺少 serialVersionUID 定义时的警告;
finally
:任何 finally 子句不能正常完成时的警告;
unused
:代码中的变量或方法没有被使用产生的警告;
rawtypes
:使用泛型时没有指定类型的警告;Override
:覆盖,重写,用于修饰方法覆盖了父类的方法。
元注解(存在于在注解类型上的注解类型),通常是用来对其他注解类型作说明。
java.lang.annotation包中的注解类型:
Documented
:指定注解类型将通过javadoc和类似的默认工具进行文档化。Inherited
:指定注解类型被自动继承。Retention
:指定注解类型保持到哪个时期,也就是指定注解的生命周期
。注解的生命周期
java源文件阶段(编译时)——>>class文件阶段——>>内存中的字节码阶段(运行时)
@Retention 参数取值于枚举类型:
java.lang.annotation.ElementType
SOURCE
: 在源文件中有效(即源文件保留)
CLASS
: 在class文件中有效(即class保留)
RUNTIME
: 在运行时有效(即运行时保留)Target
:指定注解类型适用的注解位置。如:@Target(ElementType.TYPE)。
描述注解的修饰的范围,指定注解可用于修饰package、类、接口、枚举、注解、方法、构造方法、成员变量、枚举值、方法参数、本地变量(如循环变量)。@Target 参数取值于枚举类型:
java.lang.annotation.RetentionPolicy
CONSTRUCTOR
: 用于描述构造器
FIELD
: 用于描述成员变量
LOCAL_VARIABLE
: 用于描述局部变量
METHOD
: 用于描述方法
PACKAGE
: 用于描述包
PARAMETER
: 用于描述参数
TYPE
: 用于描述类、接口(包括注解类型) 或enum声明
ANNOTATION_TYPE
: 用于将注解定义为一个元注解
自定义的注解
public @interface Color{ public String value() default “red”; }
使用@interface声明,其自动继承了java.lang.annotation.Annotation接口,不需要也不能再继承其他接口或注解。
其中value()
方法代表定义了一个属性(一个注解可以有多个属性),方法名称value
就是属性的名称,如果只有一个方法/属性,并且名称必须为value
,则可以缺省(如:@Color(“blue”)),default "red"
是缺省值。方法/属性的值可以是基本数据类型、枚举、注解,以及这些类型的数组类型。
运行时注解信息解析识别
当一个注解类型生命周期被定义为运行时存在时,该注解才是运行时可见的,
AnnotatedElement
接口是java.lang.reflect
包中的一个接口,该接口是所有程序元素(Field、Method、Package、Class、Constructor)的父接口,通过反射获取这些元素的AnnotatedElement对象
,从而使得java.lang.reflect
包具有了读取解析运行时注解的能力。AnnotatedElement对象 主要是调用以下API开解析程序元素的注解信息:
T getAnnotation(Class annotationClass)
:返回该程序元素上存在的、指定类型的注解,如果该类型注解不存在,则返回null ;
T getDeclaredAnnotation(Class)
:返回该程序元素上存在的、指定类型的注解,如果该类型注解不存在,则返回null;与此接口中的其他方法不同,该方法将忽略继承的注解;
Annotation[] getAnnotations()
:返回该程序元素上存在的所有注解;
Annotation[] getDeclaredAnnotations()
:返回直接存在于此元素上的所有注释。与此接口中的其他方法不同,该方法将忽略继承的注解;
Annotation[] getAnnotationsByType(Class)
:返回直接存在于此元素上指定注解类型的所有注解;
Annotation[] getDeclaredAnnotationsByType(Class)
:返回直接存在于此元素上指定注解类型的所有注解。
与此接口中的其他方法不同,该方法将忽略继承的注解;boolean isAnnotationPresent(Class<?extends Annotation> annotationClass)
:判断该程序元素上是否包含指定类型的注解,存在则返回true,否则返回false;
JDK8.0新特性
枚举ElementType新增2个类型
ElementType.TYPE_PARAMETER
: 表示该注解能写在类型变量的声明语句中;
ElementType.TYPE_USE
: 表示该注解能写在使用类型的任何语句中(例如声明语句、泛型和强制转换语句中的类型);@Target({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE}) public @interface Student{...}
使用形如:
new @Interned Student();
StudentA stuA = (@NonNull StudentA) stu;
class Entity extends @Todo Serializable{ ... }
void println() throws @ErrorApi ApiException { … }
List<@Student T> query(...);
这2个新增的类型,为新的设计和工具带来了更多的机遇。
新增
@Repeatable
注解该注解修饰赋予一个注解可以在程序元素上重复使用。
public class Teacher{ @Authority(role="ban zhu ren") @Authority(role="xiao zhang") public String role; }