1. 注解概述
【注解是什么:】
- 从 JDK 5.0 开始,Java 增加了对元数据(MetaData)的支持,也就是注解(Annotation)
- 注解其实就是代码中的 特殊标记 ,这些标记可以在编译、类加载、运行时被 JVM 读取,并执行相应的处理。通过使用注解,程序员可以在不改变原有逻辑的情况下,在源文件中嵌入一些补充信息。代码分析工具、开发工具和部署工具可以通过这些补充信息进行验证或者部署。
- 注解可以像修饰符一样被使用,可用于 修饰包、类、构造器、方法、成员变量、参数、局部变量声明 等,这些信息被保存在 Annotation 的 “name = value”键值对中。
【注解的重要性:】
- 在 JavaEE / Android 开发中,注解占据了非常重要的角色,例如用来配置应用程序的任何切面,代替 JavaEE 旧版中所遗留的繁冗代码和 XML 配置。
- 未来的开发模式都是基于注解的,JPA 是基于注解的,Spring2.5以上 都是基于注解的。注解是一种趋势,一定程度上可以说:框架 = 注解 + 反射 + 设计模式
2. 常见注解示例
3. 内置的3个基本注解
- @Override:限定重写父类方法,该注解只能用于方法
- 当在子类的某一个方法前加上@Override,就等于告诉 JVM 这个方法是重写父类的,因此在编译阶段就会进行校验这个方法是不是重写方法。如果不是,编译就会报错。
- @Deprecated:用于表示所修饰的元素(类、方法等)已过时。通常是因为所修饰的结构危险或存在更好的选择
- 比如,当 JDK 版本更新时,新版本会向下兼容旧版本。意思时,新版本会提供一些能够代替旧版一些结构的新结构,那些旧结构虽然不用了,但是仍然可以用,没有任何问题。
- @SuppressWarnings:抑制编译器警告
a、b 都没有被用过,所以会报灰,@SuppressWarnings(“unused”)会抑制编译器的这个操作,所以b就亮了。
4. 自定义注解
在interface前加@就行,参考SuppressWarnings源码:
public @interface SuppressWarnings {
/**
* The set of warnings that are to be suppressed by the compiler in the
* annotated element. Duplicate names are permitted. The second and
* successive occurrences of a name are ignored. The presence of
* unrecognized warning names is <i>not</i> an error: Compilers must
* ignore any warning names they do not recognize. They are, however,
* free to emit a warning if an annotation contains an unrecognized
* warning name.
*
* <p> The string {@code "unchecked"} is used to suppress
* unchecked warnings. Compiler vendors should document the
* additional warning names they support in conjunction with this
* annotation type. They are encouraged to cooperate to ensure
* that the same names work across multiple compilers.
* @return the set of warnings to be suppressed
*/
String[] value();
}
自定义注解举例:
package pkg11;
public @interface MyAnnotation {
String value() default "123" ; // default 代表默认值
}
自定义注解的使用: <br /><br />当然这个注解没有任何用。<br />【**总结】**
- 注解声明为: @interface
- 内部定义成员,通常使用 value 表示。
- 成员的形式均为无参方法。
- 可以指定成员的默认值,使用 default 定义。
- 如果自定义注解没有成员,表明是一个标识作用。
- 如果注解有成员且没有默认值,则在使用时需要指明成员的值。
- 自定义注解必须配上注解的信息处理流程(使用反射)才有意义,这点在学反射时会细说。
5. JDK 的4个元注解
所谓元注解,就是对现有注解进行修饰的注解。JDK5.0 提供了4个标准的元注解(meta-annotation)类型,分别是:
- Retention
- Target
- Document
- Inherited
比如,打开 @Override 发现该注解上面还有两个注解,这两个注解就是用来对现有注解 @Override 进行修饰的元注解:
Retention:用来指明现有注解的生命周期。
RetentionPolicy 类型源码:
public enum RetentionPolicy {
/**
* Annotations are to be discarded by the compiler.
*/
SOURCE,
/**
* Annotations are to be recorded in the class file by the compiler
* but need not be retained by the VM at run time. This is the default
* behavior.
*/
CLASS,
/**
* Annotations are to be recorded in the class file by the compiler and
* retained by the VM at run time, so they may be read reflectively.
*
* @see java.lang.reflect.AnnotatedElement
*/
RUNTIME
}
可以看到,@Override的 Retention 中的成员是 Source,说明该注释在编译成 class 文件时就会被舍弃,@SuppressWarnings 也是这样的,这是因为这些注解在运行时并不需要。但是,对于那些运行时需要调用的注解,Retention 的成员就必须要时 RUNTIME,只有这样才能在运行时通过反射来调用该注释。
Target:用于指定被修饰的 Annotation 能用于修饰哪些元素
其中,value 是一个数组,它的元素类型为 ElementType,源码为:
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
/**
* Returns an array of the kinds of elements an annotation interface
* can be applied to.
* @return an array of the kinds of elements an annotation interface
* can be applied to
*/
ElementType[] value();
}
点开 SuppressWarnings,发现其 @Target 的 value 数组七个值全有,如下图所示。说明 @SuppressWarnings 可以修饰 构造器、域、局部变量、方法、包、参数、类、接口、enum声明。<br /><br />如果一个现有注解没有 指定 Target,则默认可以修饰任何结构,等价于 Target 成员七个值全由,如前文自定义的 MyAnnotation,其可以修饰任何结构:<br /><br />一般而言,自定义注解时都会用到** @Retention **和 **@Target**
@Documented 和 @Inherited : 这两个基本不会用到,了解下就行
6. JDK8 的新特性
6.1 可重复注解
首先,自定义一个注解名叫 MyAnnotations,其成员是一个现有注解的数组,如 MyAnnotation[];
MyAnnotation:
package pkg11;
public @interface MyAnnotation {
String value() default "123" ; // default 代表默认值
}
MyAnnotations:
package pkg11;
public @interface MyAnnotations {
MyAnnotation[] value();
}
在 Java 8 之前,必须通过在待注解结构前使用 @MyAnnotations 才能对该结构进行重复 @MyAnnotation 注解修饰,具体格式为:
@MyAnnotations({@MyAnnotation("234"),@MyAnnotation("567")})
private String name ;
但是,在 Java8 中增加了 @Repeatable 注解,用来指明一个注解是可以重复修饰一个结构的。其用法为;在自定义的注解前加上 @Repeatable(MyAnnotations.class) 注解,其中 MyAnnotations.class 是固定格式,MyAnnotations 是以 MyAnnotation 数组为成员的注解。
这样一来,@MyAnnotation注解既可以直接重复修饰一个结构:
要注解的是,如果 @Repeatable(MyAnnotations.class) 想要成功,那么 MyAnnotations 和 MyAnnotation 的@Target 和 @Retention 的成员必须满足包含关系,即MyAnnotation的修饰目标、生命周期必须大于等于MyAnnotations ,否则 @Repeatable 会直接报错。
【例1:】
MyAnnotation:
MyAnnotations:
【例2:】
MyAnnotation:
MyAnnotations:
一般都采用例2的方式,即让二者一样。
6.2 类型注解
在 Java8 中,@Target 中的 ElementType 在原有的7个成员上有加了两个成员:
- TYPE_PARAMETER 表示该注解能写在类型变量的声明语句中(如:泛型)。
- TYPE_USE 表示该注解能写在使用类型的任何语句中。