简介
是JDK1.5及以后版本引入的一个特性,与类、接口、枚举是在同一个层次。它可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明.
从JVM的角度看,注解本身对代码逻辑没有任何影响,如何使用注解完全由工具决定.
Java的注解可以分为三类: 编译器使用的注解, 工具处理.class文件使用的注解, 程序运行期能够读取的注解
底层
java Annotation 的组成中,有 3 个非常重要的主干类
interface Annotation
package java.lang.annotation;
public interface Annotation {
boolean equals(Object obj);
int hashCode();
String toString();
Class<? extends Annotation> annotationType();
}
enum ElementType
package java.lang.annotation;
public enum ElementType {
TYPE, /* 类、接口(包括注释类型)或枚举声明 */
FIELD, /* 字段声明(包括枚举常量) */
METHOD, /* 方法声明 */
PARAMETER, /* 参数声明 */
CONSTRUCTOR, /* 构造方法声明 */
LOCAL_VARIABLE, /* 局部变量声明 */
ANNOTATION_TYPE, /* 注释类型声明 */
PACKAGE /* 包声明 */
}
enum RetentionPolicy
package java.lang.annotation;
public enum RetentionPolicy {
SOURCE, /* Annotation信息仅存在于编译器处理期间,编译器处理完之后就没有该Annotation信息了 */
CLASS, /* 编译器将Annotation存储于类对应的.class文件中。默认行为 */
RUNTIME /* 编译器将Annotation存储于class文件中,并且可由JVM读入 */
}
编译器使用的注解
这类注解不会被编译进入.class文件,它们在编译后就被编译器扔掉了。
- @Override:让编译器检查该方法是否正确地实现了覆写;
- @SuppressWarnings:告诉编译器忽略此处代码产生的警告。
工具处理.class文件使用的注解
有些工具会在加载class的时候,对class做动态修改,实现一些特殊的功能。
这类注解会被编译进入.class文件,但加载结束后并不会存在于内存中。
这类注解只被一些底层库使用,一般我们不必自己处理。
程序运行期能够读取的注解
它们在加载后一直存在于JVM中,这也是最常用的注解.
注解的使用
定义一个注解时,可以定义配置参数, 但是参数必须是常量.
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
/**
* 检查类中字段是否符合规则
*/
public @interface Check {
int maxLen() default 20; // 字段最大长度,默认20个字符
}
/**
* 用户信息类
*/
public class User {
@Check(maxLen=10)
/** 用户名,最大长度10个字符 */
String name = "";
}
/**
* 测试类
*/
public class Test {
public static void main(String[] args) {
User user = new User();
user.name = "123123";
checkField(user);
user.name = "123123123123";
checkField(user);
}
public static boolean checkField(Object obj) {
Field[] fields = obj.getClass().getFields();
for(Field field : fields) {
Check check = field.getAnnotation(Check.class);
if(field.get(obj).toString().length() > check.maxLen()) {
throw new Exception(field.getName() + "字段长度太长");
} else {
System.out.println(field.getName() + "字段长度通过验证");
}
}
}
}