注解Annotation
概念相关
JDK5开始,java增加了对元数据(MetaData)的支持,也就是Annotation。
Annotation其实就是代码里的特殊标记,这些编辑可以在编译、类加载、运行的时候被读取,并执行相应的处理。可以实现不改变原有逻辑的情况下,源代码中嵌入补充信息。
它是一种程序元素(类、方法、成员变量等)的元数据,不会影响程序逻辑。
注解分类
根据注解参数的个数分类
- 标记注解:一个没有成员定的以的Annotation;这种Annotation类型仅适用自身的存在与否来为我们提供信息。
- 单值注解:只存在 value = "xxx";通常@Annotation("xxx");value=可以省略
- 完整注解
根据注解适用方法和用途分类
- JDK内置系统注解
- 元注解:标记其它注解的注解
- 自定义注解
JDK常用的注解
-
@Override : 重写方法
-
@Deprecated : 表示某个程序元素(类、方法等)已经过时
-
@SuppressWarnings : 抑制编译器警告
-
@SafeVarargs : 堆污染警告(java7出现)
堆污染:把一个不带泛型的对象赋给一个带泛型的变量
List list = new ArrayList<Integer>(); list.add(20); List<String> ls = list; System.out.println(ls.get(0));
-
@Functionallnterface : 函数式接口
接口中只有一个抽象方法,该接口就是函数式接口,@FunctionalInterface 就是用来执行某个接口必须是函数式接口。
JDK元Annotation
5个元Annotation 用于修饰其它Annotation的定义
-
@Retention : 用于执行被修饰的Annotation可以保留多长时间
value的值:
RetentionPolicy.CLASS : 编译器把Annotation记录在class中,当运行java程序时,jvm获取不到,默认值
RetentionPolicy.RUNTIME:编译器把Annotation记录在class中,当运行java程序时,jvm可以获取到Annotation信息,程序可以通过反射获取Annotation信息
RetentionPolicy.SOURCE:编译器把Annotation记录在源码中,class中丢失该Annotation
@Retention(value=RetentionPolicy.RUNTIME) public @interface Test{}
说明:如果使用注解只为value成员变量指定值时,可以括号内直接指定value,如:
@Retention(RetentionPolicy.RUNTIME) public @interface Test{}
-
@Target
@Target 只能修饰一个Annotation,用于指定被修饰的Annotation能用于修饰在什么地方
value 说明 ElementType.ANNOTATION_TYPE 只能修饰Annotation ElementType.CONSTRUCTOR 构造器 ElementType.FIELD 成员变量 ElementType.LOCAL_VARIABLE 局部变量 ElementType.METHOD 方法 ElementType.PACKAGE 包 ElementType.PARAMETER 参数 ElementType.TYPE 类、接口、枚举 -
@Documented
用于指定被@Documented修饰的annotation修饰的类被javadoc工具提取成文档
-
@Inherited
用于指定被@Inherited修饰的annotation修饰的类,具有继承性;如类A使用了@xxx (@xxx被@Inherited修饰),那么继承类A的子类a会自动被@xxx修饰(无需显示手动写出)
自定义注解
格式:
public @interface AnnotationName { ... }
说明:
使用@interface自定义注解时,自动继承了java.lang.annotation.Annotation接口,由编译程序自动完成的。在定义注解时候,不能继承其它的注解或者接口。
注解支持的数据类型
- 基本类型(不支持包装类型)
- String类型
- Class类型
- enum类型
- Annotation类型
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AnnotationDemo {
int value() default 0;
String name() default "";
}
注解的运行原理
注解本质是一个继承了Annotation的特殊接口,其具体的实现类是java运行时生成的动态代理类(Debug是,可以看到动态代理对象$Proxy1,通过代理对象调用自定义注解(接口)的方法,会最终调用AnnotationInvocationHandler
的invoke
方法。该方法会从memberValues
这个Map 中索引出对应的值。而memberValues
的来源是Java 常量池)。通过反射获取注解相关信息。
注解处理类(AnnotatedElement;也叫注解处理器),获取注解信息。
Annotation接口,代表注解的注解,是所有注解的父接口
AnnotatedElement接口,代表程序中可以接受注解的程序元素;该接口也叫注解处理器;如图:
AnnotatedElement-UML.png-
<T extends Annotation> T getAnnotation(Class<T> annotationClass)
返回程序元素上存在的指定类型的注解,若不存在,则返回null
-
Annotation[] getAnnotations()
返回该程序元素上存在的所有注解
-
boolean is AnnotationPresent(Class<?extends Annotation> annotationClass)
判断程序元素上是否包含指定类型的注解
-
Annotation[] getDeclaredAnnotations()
返回直接存在于此元素上的所有注解(忽略继承的注解)
获取注解的过程;也就是上述五个继承类中(注解处理器),getAnnotations 的过程:
客户端代码:
Field name = client.getClass().getDeclaredField("name");
AnnotationDemo annotation = name.getAnnotation(AnnotationDemo.class);
Field.java
public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
Objects.requireNonNull(annotationClass);
return annotationClass.cast(declaredAnnotations().get(annotationClass));
}
private synchronized Map<Class<? extends Annotation>, Annotation> declaredAnnotations() {
if (declaredAnnotations == null) {
Field root = this.root;
if (root != null) {
declaredAnnotations = root.declaredAnnotations();
} else {
declaredAnnotations = AnnotationParser.parseAnnotations(
annotations,
sun.misc.SharedSecrets.getJavaLangAccess().getConstantPool(getDeclaringClass()),
getDeclaringClass());
}
}
return declaredAnnotations;
AnnotationParser.class
public static Map<Class<? extends Annotation>, Annotation> parseAnnotations(byte[] var0, ConstantPool var1, Class<?> var2) {
if (var0 == null) {
return Collections.emptyMap();
} else {
try {
return parseAnnotations2(var0, var1, var2, (Class[])null);
} catch (BufferUnderflowException var4) {
throw new AnnotationFormatError("Unexpected end of annotations.");
} catch (IllegalArgumentException var5) {
throw new AnnotationFormatError(var5);
}
}
}
private static Map<Class<? extends Annotation>, Annotation> parseAnnotations2(byte[] var0, ConstantPool var1, Class<?> var2, Class<? extends Annotation>[] var3) {
LinkedHashMap var4 = new LinkedHashMap();
ByteBuffer var5 = ByteBuffer.wrap(var0);
int var6 = var5.getShort() & '\uffff';
for(int var7 = 0; var7 < var6; ++var7) {
Annotation var8 = parseAnnotation2(var5, var1, var2, false, var3);
if (var8 != null) {
Class var9 = var8.annotationType();
if (AnnotationType.getInstance(var9).retention() == RetentionPolicy.RUNTIME && var4.put(var9, var8) != null) {
throw new AnnotationFormatError("Duplicate annotation for class: " + var9 + ": " + var8);
}
}
}
return var4;
}
private static Annotation parseAnnotation2(ByteBuffer var0, ConstantPool var1, Class<?> var2, boolean var3, Class<? extends Annotation>[] var4) {
int var5 = var0.getShort() & '\uffff';
Class var6 = null;
String var7 = "[unknown]";
try {
try {
var7 = var1.getUTF8At(var5);
var6 = parseSig(var7, var2);
} catch (IllegalArgumentException var18) {
var6 = var1.getClassAt(var5);
}
} catch (NoClassDefFoundError var19) {
if (var3) {
throw new TypeNotPresentException(var7, var19);
}
skipAnnotation(var0, false);
return null;
} catch (TypeNotPresentException var20) {
if (var3) {
throw var20;
}
skipAnnotation(var0, false);
return null;
}
if (var4 != null && !contains(var4, var6)) {
skipAnnotation(var0, false);
return null;
} else {
AnnotationType var8 = null;
try {
var8 = AnnotationType.getInstance(var6);
} catch (IllegalArgumentException var17) {
skipAnnotation(var0, false);
return null;
}
Map var9 = var8.memberTypes();
LinkedHashMap var10 = new LinkedHashMap(var8.memberDefaults());
int var11 = var0.getShort() & '\uffff';
for(int var12 = 0; var12 < var11; ++var12) {
int var13 = var0.getShort() & '\uffff';
String var14 = var1.getUTF8At(var13);
Class var15 = (Class)var9.get(var14);
if (var15 == null) {
skipMemberValue(var0);
} else {
Object var16 = parseMemberValue(var15, var0, var1, var2);
if (var16 instanceof AnnotationTypeMismatchExceptionProxy) {
((AnnotationTypeMismatchExceptionProxy)var16).setMember((Method)var8.members().get(var14));
}
var10.put(var14, var16);
}
}
return annotationForMap(var6, var10);
}
}
public static Annotation annotationForMap(final Class<? extends Annotation> var0, final Map<String, Object> var1) {
return (Annotation)AccessController.doPrivileged(new PrivilegedAction<Annotation>() {
public Annotation run() {
//该句是重点;返回动态代理对象
return (Annotation)Proxy.newProxyInstance(var0.getClassLoader(), new Class[]{var0}, new AnnotationInvocationHandler(var0, var1));
}
});
}
class AnnotationInvocationHandler implements InvocationHandler, Serializable {
private static final long serialVersionUID = 6182022883658399397L;
private final Class<? extends Annotation> type;
//该句是重点:对象池
private final Map<String, Object> memberValues;
private transient volatile Method[] memberMethods = null;
AnnotationInvocationHandler(Class<? extends Annotation> var1, Map<String, Object> var2) {
Class[] var3 = var1.getInterfaces();
if (var1.isAnnotation() && var3.length == 1 && var3[0] == Annotation.class) {
this.type = var1;
this.memberValues = var2;
} else {
throw new AnnotationFormatError("Attempt to create proxy for a non-annotation type.");
}
}
public Object invoke(Object var1, Method var2, Object[] var3) {
}
}
网友评论