1.1 注解(Annotation)
1.1.1 什么是注解
注解的定义:它提供了一种安全的类似注释的机制,用来将任何信息或元数据(metadata)与程序元素(类、方法、成员变量等)进行关联。为程序的元素(类、方法、成员变量)加上更直观、更明了的说明,这些说明信息与程序的业务逻辑无关,并且供指定的工具或框架使用。
注解不会也不能影响代码的实际逻辑,仅仅起到辅助性的作用,包含在
java.lang.annotation
包中。
1.1.2 内置注解
@Deprecated
:@Deprecated 所标注内容,不再被建议使用。——会发出程序元素(类、方法、成员变量)过时的提醒警告。@Override
:@Override 只能标注方法,表示该方法覆盖父类中的方法。——提示子类重写父类中被 @Override 修饰的方法。@SuppressWarnings
:@SuppressWarnings 所标注内容产生的警告,编译器会对这些警告保持静默。——阻止警告,例如忽略因调用被 @Deprecated 注解的方法而发出的警告。@SafeVarargs
:参数安全类型注解。它的目的是提醒开发者不要用参数做一些不安全的操作,它的存在会阻止编译器产生 unchecked 这样的警告。它是在 Java 1.7 的版本中加入的。@FunctionalInterface
:函数式接口注解,这个是在 Java 1.8 版本引入的新特。函数式接口(Functional Interface)就是一个具有一个方法的普通接口。
1.1.3 元注解(5种)
java.lang.annotation
提供了5种元注解,专门注解其他的注解。
@Retention
:什么时候使用该注解。@Target
:注解用于什么地方。@Documented
:注解是否将包含在 JavaDoc 中。@Inherited
:是否允许子类继承该注解。@Repeatable
:指定注解可重复使用。
1.
@Retention
定义注解的生命周期注解
@Retention
的定义:@Documented @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.ANNOTATION_TYPE) public @interface Retention { /** * Returns the retention policy. * @return the retention policy */ RetentionPolicy value(); }
package java.lang.annotation; public enum RetentionPolicy { SOURCE, /* Annotation信息仅存在于编译器处理期间,编译器处理完之后就没有该Annotation信息了 */ CLASS, /* 编译器将Annotation存储于类对应的.class文件中。默认行为 */ RUNTIME /* 编译器将Annotation存储于class文件中,并且可由JVM读入 */ }
- RetentionPolicy.SOURCE:信息之保留在源码中,编译时将丢弃。——在编译阶段丢弃。这些注解在编译结束之后不再有任何意义,所以他们不会写入字节码。
@Override
和@SuppressWarnings
都属于这类注解。- RetentionPolicy.CLASS:信息只保留在源码和编译后的class文件中,但加载到JVM时将被丢弃。——在类加载的时候丢弃。在字节码文件的处理中有用。注解默认使用这种方式。
- RetentionPolicy.RUNTIME:信息将保留在源码、class文件以及运行时。——始终不会丢弃,运行期也保留该注解,因此可以使用反射机制读取该注解的信息。我们自定义注解通常使用这种方式。
2.
@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(); }
package java.lang.annotation; public enum ElementType { TYPE, /* 类、接口(包括注释类型)或枚举声明 */ FIELD, /* 字段声明(包括枚举常量) */ METHOD, /* 方法声明 */ PARAMETER, /* 参数声明 */ CONSTRUCTOR, /* 构造方法声明 */ LOCAL_VARIABLE, /* 局部变量声明 */ ANNOTATION_TYPE, /* 注释类型声明 */ PACKAGE /* 包声明 */ }
ElementType.TYPE:用于描述类、接口(包括注解类型)或enum声明。
ElementType.FIELD:成员变量、对象、属性(包括enum实例)。
ElementType.METHOD:用于描述方法。
ElementType.PARAMETER:用于描述参数。
ElementType.CONSTRUCTOR:用于描述构造器。
ElementType.LOCAL_VARIABLE:用于描述局部变量。
ElementType.ANNOTATION_TYPE:用于注解声明(应用于另一个注解上)。
ElementType.PACKAGE:用于描述包。
3.
@Documented
是一个简单的 Annotations 标记注解
@Documented
表示是否将注解信息添加在 Java 文档中。4.
@Inherited
定义注解和子类的关系
@Inherited
元注解是一个标记注解,阐述了某个被标注的类型是被继承的。如果一个使用了@Inherited
修饰的 annotation(注解) 类型被用于一个class(类),那么这个 annotation 将被用于该 class 的子类。5.
@Repeatable
指定注解可重复使用使用
@Repeatable
修饰表示该注解可以为重复使用。
1.14 自定义注解
元注解是负责注解自定义注解的。
自定义注解时是有一些规则限制的,具体如下:
- Annotation 型定义为
@interface
,所有的 Annotation 会自动继承java.lang.annotation.Annotation
这一接口,并且不能再去继承别的类或是接口。 - 参数成员只能用
public
或默认(default
)这两个访问权修饰。 - 参数成员只能用基本类型
byte
、short
、char
、int
、long
、float
、double
、boolean
八种基本数据类型和String
、Enum
、Class
、Annotation
等数据类型,以及这一些类型的数组。 - 要获取类方法和字段的注解信息,必须通过 Java 的反射技术来获取 Annotation 对象,因为除此之外没有其他获取注解对象的方法。
- 注解也可以没有定义成员。
Annotation 的定义:
package java.lang.annotation; public interface Annotation { boolean equals(Object obj); int hashCode(); String toString(); Class<? extends Annotation> annotationType(); }
1.15 注解使用场景介绍
注解应用的场景很多,下面列举几个使用场景。
(1)使用注解做 bean 的属性值校验。
例如在开发 Java 服务器端代码时,会要求对外部传来的参数合法性进行验证。hibernate-validator 提供了一些常用的参数校验注解。
(2)使用注解做权限控制。
例如 shiro 框架中有5个权限注解,我们也可以自定义注解进行权限控制。
(3)代替配置文件功能。
像 Spring 基于注解的配置,减少了 xml 的配置。
(4)可以生成文档。
像 Java 代码注释中的 @see、@param 等。
※ 本文小结
来源:《Spring 快速入门 / 崔彦威,卢欣欣,王倩著》 学习笔记