[关闭]
@xiu-tanwy 2016-11-21T09:23:48.000000Z 字数 4540 阅读 483

java 注解之原理讲解

java-grammar


注解的作用

Annotation(注解)是JDK5.0及以后版本引入的。它的作用是修饰编程元素。什么是编程元素呢?例如:包、类、构造方法、方法、成员变量等。

注解的作者

注解是JDK 5.0推出来的,这部分JDK源码的作者是:Joshua Bloch,这是一个技术大牛。Collections Framework皆是他一手打造,还获得了当年的Jolt大奖。另外,他还写了一本非常出名的书:《Effective Java》

注解解释

java中的注解是一种继承自接口java.lang.annotation.Annotation的特殊接口。参见下面的JDK文档。

  1. An annotation type declaration specifies a new annotation type,
  2. a special kind of interface type. To distinguish an annotation(区分)
  3. type declaration from a normal interface declaration, the keyword
  4. interface is preceded by an at-sign (@).
  5. ...
  6. The direct superinterface of every annotation type is java.lang.annotation.Annotation.

注解的语法与定义形式

(1)以@interface关键字定义
(2)注解包含成员,成员以无参数的方法的形式被声明。其方法名和返回值定义了该成员的名字和类型。
(3)成员赋值是通过@Annotation(name=value)的形式。
(4)注解需要标明注解的生命周期,注解的修饰目标等信息,这些信息是通过元注解实现。
上面的语法不容易理解,下面通过例子来说明一下,这个例子就是Target注解的源码,

  1. import java.lang.annotation.ElementType;
  2. import java.lang.annotation.Retention;
  3. import java.lang.annotation.RetentionPolicy;
  4. @Retention(value = RetentionPolicy.RUNTIME)
  5. @Target(value = {ElementType.ANNOTATION_TYPE})
  6. public @interface Target {
  7. /**
  8. * Returns an array of the kinds of elements an annotation type
  9. * can be applied to.
  10. * @return an array of the kinds of elements an annotation type
  11. * can be applied to
  12. */
  13. ElementType[] value();
  14. }

源码分析如下:
第一:元注解@Retention,成员value的值为RetentionPolicy.RUNTIME。
第二:元注解@Target,成员value是个数组,用{}形式赋值,值为ElementType.ANNOTATION_TYPE
第三:成员名称为value,类型为ElementType[]
另外,需要注意一下,如果成员名称是value,在赋值过程中可以简写。如果成员类型为数组,但是只赋值一个元素,则也可以简写。如上面的简写形式为:

  1. @Retention(RetentionPolicy.RUNTIME)
  2. @Target(ElementType.ANNOTATION_TYPE)

注解的分类

注解分为两类,一类是元注解,另外一类是普通注解。
所谓元注解就是修饰注解的注解。
拿到一个注解,如何知道它是否是元注解呢?需要看它的元注解(无论是元注解还是普通注解都是有元注解的),如果看到这样的元注解:@Target(ElementType.ANNOTATION_TYPE),那么此时这个注解一定是元注解。

注解的生命周期

注解的定义语法中已经说到了:注解需要标明注解的生命周期,这些信息是通过元注解实现。而这个元注解是:

  1. public @interface Retention
  2. {
  3. RetentionPolicy value();
  4. }
  5. public enum RetentionPolicy {
  6. /**
  7. * Annotations are to be discarded by the compiler.
  8. */
  9. SOURCE,
  10. /**
  11. * Annotations are to be recorded in the class file by the compiler
  12. * but need not be retained by the VM at run time. This is the default
  13. * behavior.
  14. */
  15. CLASS,
  16. /**
  17. * Annotations are to be recorded in the class file by the compiler and
  18. * retained by the VM at run time, so they may be read reflectively.
  19. *
  20. * @see java.lang.reflect.AnnotatedElement
  21. */
  22. RUNTIME
  23. }

Retention注解的值是enum类型的RetentionPolicy。包括如下几种情况:
(1)SOURCE: 注解只保留在源文件,当Java文件编译成class文件的时候,注解被遗弃。
(2)CLASS: 注解被保留到class文件,jvm加载class文件时候被遗弃。这是默认的生命周期。
(3)RUNTIME: 注解不仅被保存到class文件中,jvm加载class文件之后,仍然存在,保存到class对象中,可以通过反射来获取。

注解的修饰目标

注解的定义语法中已经说到了:注解需要标明注解的修饰目标,这些信息是通过元注解实现。而这个元注解是:

  1. @Documented
  2. @Retention(RetentionPolicy.RUNTIME)
  3. @Target(ElementType.ANNOTATION_TYPE)
  4. public @interface Target {
  5. ElementType[] value();
  6. }
  7. public enum ElementType {
  8. /** Class, interface (including annotation type), or enum declaration */
  9. TYPE,
  10. /** Field declaration (includes enum constants) */
  11. FIELD,
  12. /** Method declaration */
  13. METHOD,
  14. /** Parameter declaration */
  15. PARAMETER,
  16. /** Constructor declaration */
  17. CONSTRUCTOR,
  18. /** Local variable declaration */
  19. LOCAL_VARIABLE,
  20. /** Annotation type declaration */
  21. ANNOTATION_TYPE,
  22. /** Package declaration */
  23. PACKAGE
  24. }

这个注解的值是enum类型ElementType。包括以下几种情况:
(1)TYPE:指的是在类,接口(包括注解)或者enum上使用的注解。
(2)FIELD:指的在field属性,也包括enum常量使用的注解。
(3)METHOD:指的是在方法声明上使用的注解。
(4)PARAMETER:指的是在参数上使用的注解,
(5)CONSTRUCTOR: 指的是在构造器使用的注解。
(6)LOCAL_VARIABLE:指的是在局部变量上使用的注解。
(7)ANNOTATION_TYPE:指的是在注解上使用的元注解
(8)PACKAGE:指的是在包上使用的注解。

注解的底层实现

定义一个注解

  1. @Retention(RetentionPolicy.RUNTIME)
  2. @Target(ElementType.TYPE)
  3. public @interface Cache
  4. {
  5. String value() default "cache";
  6. }

分析其字节码,如下图所示:
C:\Users\Administrator\workspace\cache\bin>javap -verbose Cache

  1. Classfile /C:/Users/Administrator/workspace/cache/bin/Cache.class
  2. Last modified 2016-7-23; size 429 bytes
  3. MD5 checksum 771f9c4d63ce2ded5d3b093deebd2c69
  4. Compiled from "Cache.java"
  5. public interface Cache extends java.lang.annotation.Annotation
  6. minor version: 0
  7. major version: 52
  8. flags: ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION
  9. Constant pool:
  10. #1 = Class #2 // Cache
  11. #2 = Utf8 Cache
  12. #3 = Class #4 // java/lang/Object
  13. #4 = Utf8 java/lang/Object
  14. #5 = Class #6 // java/lang/annotation/Annotation
  15. #6 = Utf8 java/lang/annotation/Annotation
  16. #7 = Utf8 value
  17. #8 = Utf8 ()Ljava/lang/String;
  18. #9 = Utf8 AnnotationDefault
  19. #10 = Utf8 cache
  20. #11 = Utf8 SourceFile
  21. #12 = Utf8 Cache.java
  22. #13 = Utf8 RuntimeVisibleAnnotations
  23. #14 = Utf8 Ljava/lang/annotation/Retention;
  24. #15 = Utf8 Ljava/lang/annotation/RetentionPolicy;
  25. #16 = Utf8 RUNTIME
  26. #17 = Utf8 Ljava/lang/annotation/Target;
  27. #18 = Utf8 Ljava/lang/annotation/ElementType;
  28. #19 = Utf8 TYPE
  29. {
  30. public abstract java.lang.String value();
  31. descriptor: ()Ljava/lang/String;
  32. flags: ACC_PUBLIC, ACC_ABSTRACT
  33. AnnotationDefault:
  34. default_value: s#10
  35. }
  36. SourceFile: "Cache.java"
  37. RuntimeVisibleAnnotations:
  38. 0: #14(#7=e#15.#16)
  39. 1: #17(#7=[e#18.#19])

分析上面的字节码,我们可以得出:
第一:public interface Cache extends java.lang.annotation.Annotation,说明Cache注解是继承自Annotation,仍然是interface。
第二:public abstract java.lang.String value(),说明value方法是abstract类型。

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注