注解的理解
① jdk 5.0 新增的功能
② Annotation 其实就是代码里的特殊标记, 这些标记可以在编译, 类加载, 运行时被读取, 并执行相应的处理。通过使用 Annotation,程序员可以在不改变原逻辑的情况下, 在源文件中嵌入一些补充信息。
③在JavaSE中,注解的使用目的比较简单,例如标记过时的功能,忽略警告等。在JavaEE/Android中注解占据了更重要的角色,例如用来配置应用程序的任何切面,代替JavaEE旧版中所遗留的繁冗代码和XML配置等。
框架 = 注解 + 反射机制 + 设计模式
注解的使用示例
-
示例一:生成文档相关的注解
-
示例二:在编译时进行格式检查(JDK内置的个基本注解)
@Override: 限定重写父类方法, 该注解只能用于方法
@Deprecated: 用于表示所修饰的元素(类, 方法等)已过时。通常是因为所修饰的结构危险或存在更好的选择
@SuppressWarnings: 抑制编译器警告 -
示例:跟踪代码依赖性,实现替代配置文件功能
如何自定义注解:参照@SuppressWarnings定义
- ① 注解声明为:@interface
- ② 内部定义成员,通常使用value表示
- ③ 可以指定成员的默认值,使用default定义
- ④ 如果自定义注解没成员,表明是一个标识作用。
说明:
如果注解有成员,在使用注解时,需要指明成员的值。
自定义注解必须配上注解的信息处理流程(使用反射)才意义。
自定义注解通过都会指明两个元注解:Retention、Target
代码举例1:
@Inherited
@Repeatable(MyAnnotations.class)
@Retention(RetentionPolicy.RUNTIME)
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE,TYPE_PARAMETER,TYPE_USE})
public @interface MyAnnotation {
String value() default "hello";
}
代码举例2:
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AutoRunMethod {
/*
注解可以定义参数。格式:类型 参数名() [default 默认值]
如下:
int value()
当定义了该参数后,那么使用注解时可以为其传递参数值,如:
@AutoRunMethod(8) 此时value参数值为:8
参数可以声明默认值,如:
int value() default 1;
当使用该注解不传入参数时,该参数采取默认值。
@AutoRunMethod 此时value参数默认值就是1
如果没有指定默认值,那么参数必须传值!!
注意:如果当前注解仅指定了一个参数,那么参数名尽量使用value。这样外面给该参数传值时可省去参数名。
如:
@AutoRunMethod(8) 此时value参数的值为8
否则,正常使用注解传参的语法格式为:@注解名(参数名=参数值)
例如:
当前注解中指定的参数为:
int count;
此时使用当前注解并传参时应当写为:
@AutoRunMethod(count=2)
两个以上参数时,无论哪个参数的名字叫value都要用name=value的格式传递参数。
例如当前注解定义了两个参数:
int count();
String name();
那么使用当前注解传参时的格式:
@AutoRunMethod(count=7,name="张三")
注意:这里传参的顺序可以和参数定义的顺序不一致。即:
@AutoRunMethod(name="张三",count=7)也是允许的。
*/
int value() default 1;
// int count();
// String name();
}
元注解 :对现有的注解进行解释说明的注解。
jdk 提供的4种元注解:
-
Target:用于指定被修饰的 Annotation 能用于修饰哪些程序元素
-
Retention:指定所修饰的 Annotation 的生命周期:SOURCE\CLASS(默认行为\RUNTIME),只有声明为RUNTIME生命周期的注解,才能通过反射获取。
-
Documented:表示所修饰的注解在被javadoc解析时,保留下来。
-
Inherited:被它修饰的 Annotation 将具继承性。
@Target的选项都被定义在ElementType中。
@Target标注,用于指定当前注解可以在什么地方被使用。
- ElementType.TYPE:在类上可以使用当前注解
- ElementType.FIELD:在属性上可以使用当前注解
- ElementType.CONSTRUCTOR:在构造方法上可以使用当前注解
- ElementType.METHOD:在方法上可以使用当前注解
- ElementType.PACKAGE:在包上可以使用当前注解
如果当前注解没有使用@Target注解标注,那么当前注解可以在任何注解可以使用的地方被应用。
如果希望同时在几个可选地方使用时,应当如下指定:
@Target({ElementType.TYPE,ElementType.METHOD,…}) 以数组形式包含可以指定位置的选项并传入@Target
@Retention注解,该注解用于标注当前注解的保留级别,有三个可选值
- RetentionPolicy.CLASS : 当前注解保留在编译后的字节码文件中,但是不可被反射机制操作。
- RetentionPolicy.SOURCE : 当前注解仅保留在源代码中。
- RetentionPolicy.RUNTIME : 当前注解保留在编译后的字节码文件中,可被反射机制操作。
注意:如果@Retention不指定,默认级别为CLASS
由于我们都是在反射机制中大量使用注解,因此我们通常要显示的标注注解的保留级别为RUNTIME!!!
如何获取注解信息:通过反射来进行获取、调用。
前提:要求此注解的元注解Retention中声明的生命周期状态为:RUNTIME.
6.JDK8中注解的新特性:可重复注解、类型注解
6.1 可重复注解:
① 在MyAnnotation上声明@Repeatable,成员值为MyAnnotations.class
② MyAnnotation的Target和Retention等元注解与MyAnnotations相同。
6.2 类型注解:
ElementType.TYPE_PARAMETER 表示该注解能写在类型变量的声明语句中(如:泛型声明。
ElementType.TYPE_USE 表示该注解能写在使用类型的任何语句中。