Java源码阅读------Annotation

描述

注解是对代码进行的标记,可以理解为代码块的标签,使用这些标签可以在源文件的信息中嵌入补充的信息,注解是一种接口,程序使用反射可以获取相应的注解对象从而获得其中的数据,实现元素数据之间的关联。

@interface

注解实际使用中是以@interface来修饰的,也就是说所有的Annotation都是以@interface来声明的,我们可以将其理解为一种特殊的interface,同理我们也比较好理解在使用注解时有@+注解名的设计了。但是注意这里的@interface与interface终究还是不同的。

Annotation

这是一个接口定义在java.lang.annotation包中。注解的实现是在这个接口上的继承与扩展,我们无法手动的继承这个接口实现注解。这个接口本身并不是注解类型。

equals

通过这个方法可以对传入的Object对象进行判断是否是一样的注解。

1
boolean equals(Object obj);

hashCode

描述注解的hash code信息。

1
int hashCode();

toString

用于返回对注解的描述信息。

1
String toString();

annotationType

返回注解的返回类型Class,这里的泛型使用也可以看出所有的类型皆有Annotation的继承关系。

1
Class<? extends Annotation> annotationType();

元注解

元注解可以对注解进行操作,可以说我们可以通过元注解来定义新的注解。

@Documented

这个注解的作用是一个标记,对应javadoc之类的工具会将其对应的注释部分加入公共的api注释中。这个注解之中没有参数。

@Target

Target注解是一个有参数的注解,其中的参数是一个ElementType的数组。

ElementType

ElementType是一个枚举类型,在1.8的版本中其中有10个值,用于在Java中注解对象的类型进行区分。通过这些值来配合Target表示对应注解的适用范围。

  1. TYPE类与接口类型
  2. FIELD字段类型
  3. METHOD方法类型
  4. PARAMETER普通的参数类型
  5. CONSTRUCTOR构造函数
  6. LOCAL_VARIABLE局部变量
  7. ANNOTATION_TYPE注释类型
  8. PACKAGE包类型
  9. TYPE_PARAMETER参数类型的声明(1.8)
  10. TYPE_USE类型的声明(1.8)
    我们在回头来看Target就很简单了。
    1
    2
    3
    public @interface Target {
    ElementType[] value();
    }

通过Target中value值的设置,可以设置相关注解的使用范围。元注解可以对自身进行注解,比如Target就有@Target(ElementType.ANNOTATION_TYPE)修饰,表示只能对注解进行注解(有点绕)。所有的元注解上都有@Target(ElementType.ANNOTATION_TYPE)修饰。

@Retention

Retention注解也是一个有参数的注解,其中的参数为一个RetentionPolicy类型的值。

RetentionPolicy

这也是一个枚举类型,定义了三个值,SOURCE,CLASS,RUNTIME。
这三个值表示了被注解的注解类型的生命周期。

  1. SOURCE只在源码阶段保留
  2. CLASS在类文件中记录,但是运行时jvm不会保留,这也是没有Retention注解时的默认设置。
  3. RUNTIME一直保留至运行状态,可以通过反射来取出。

    @Inherited

    这是一个没有参数的注解,使用这个注解去注解父类其子类就也会实现改注解(不论其子类是否含有其他注解),子类可以通过反射可以得到父类中Inherited声明的注解。
    1
    2
    3
    4
    5
    @Documented
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.ANNOTATION_TYPE)
    public @interface Inherited {
    }

@Repeatable

这是1.8中新提供的一个元注解,通过这个注解的使用我们可以对同一注解赋多个值来共同对同一代码段实行重复注解。简单看个例子:
由于是要进行重复的注解,所有需要一个容器来存储这多个注解。

1
2
3
4
5
6
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Container{
Item[] value();
}

之后就是定义实际需要的注解。

1
2
3
4
5
6
7
@Documented
@Retention(RetentionPolicy.RUNTIME)        
@Target(ElementType.TYPE)           
@Repeatable(Container.class)//这里指向的就是上文中声明的容器
public @interface Item{
String value() default "";//参数为字符串,默认值为""
}

这样就可以使用了:

1
2
3
4
5
6
7
8
9
@Item(value="A")
@Item(value="B")
public class A{

}
//或者
@Container({@Item("A"),@Item("B")})
public class A{
}

其他注解

其他的注解都是建立在元注解的基础上建立的,我们简单的看几个。

@Override

这个注解大家应该很熟悉了,当方法被重载时使用这一注解,实际上也只是一个注解,在源代码阶段使用RetentionPolicy.SOURCE,编译的使用就会失效,作用域为所有的函数ElementType.METHOD。

1
2
3
4
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}

@Native

这个注解是用于标记本地方法的,与Override相似也只是在RetentionPolicy.SOURCE阶段使用,作用范围为ElementType.FIELD。

1
2
3
4
5
@Documented
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.SOURCE)
public @interface Native {
}

注解参数

注解中可用的参数类型有:

  1. 基本数据类型(int, double, float, boolean, char, long, short, byte)
  2. String类型
  3. 注解类型(例如Repeatable注解的例子)
  4. Class类
  5. Enum类型
  6. 以上类型的数组