in java annotation 注解 Repeatable ~ read.

Java中的注解

本文基于JDK 1.8.0_45


一个简单的注解的例子

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.CONSTRUCTOR, ElementType.METHOD})
public @interface MyAnnotation {  
    String value();
}

以上是一个简单的注解的例子,从中可以看到:

  1. 通过@interface标识这个类是一个注解;
  2. 通过在注解类上加上注解来标识这个注解的元信息;
  3. 注解可以通过定义一些方法来给注解添加更多的信息;

所有的注解类型都会自动的继承自Annotation接口。该接口主要是提供给Class来使用,比如反射等。

请注意显式的实现Annotation接口并不会定义一个注解类型,该接口也不会定义一种注解类型。

该接口提供了基本的equals、hashCode、toString和annotationType方法,其中annotationType会返回相应注解实际上的class。

内置注解-Documented

变量

用法

  1. 只能用于其他注解上;
  2. 该注解用于标识它需要被JavaDoc之类的工具处理,并被包括在生成的文档中;

例子

package com.oomlife.java.example;

import java.lang.annotation.*;

@AnnotationExample.MyAnnotation("annotation example")
public class AnnotationExample {

    @Documented
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.TYPE)
    public @interface MyAnnotation {
        String value();
    }
}

使用以下命令生成JavaDoc,注意一定要加上UTF-8,否则可能会出现中文乱码。

javadoc -charset "UTF-8" -encoding "UTF-8" -d ./target/javadoc/ -author -version src/main/java/com/oomlife/java/example/AnnotationExample.java

以下是生成的JavaDoc,其中包含了注解相关的信息。

com.oomlife.java.example  
类 AnnotationExample

java.lang.Object  
        com.oomlife.java.example.AnnotationExample

@AnnotationExample.MyAnnotation(value="annotation example")
public class AnnotationExample  
extends java.lang.Object  

内置注解-Inherited

变量

用法

  1. 只能用于其他注解上;
  2. 该注解用于标识被注解的注解是会自动被继承的;
  3. 当用户从一个class上查找被该注解标识的注解A时,如果该class没有找到,会自动的从其父类上找,直到找到Object类为止,如果全部都没有找到,则认为该class没有被注解A标识;
  4. 被该注解标识的注解只有放在class上的时候用法3才会生效;

例子

1    @Documented  
2    @Inherited  
3    @Retention(RetentionPolicy.RUNTIME)  
4    @Target(ElementType.TYPE)  
5    public @interface MyAnnotation {  
6        String value();  
7    }  
8  
9    @MyAnnotation("parent class")  
10   public static class Parent {  
11   }  
12  
13   public static class Child extends Parent {  
14   }  
15  
16   public static void main(String[] args) {  
17       System.out.println(Child.class.getAnnotation(MyAnnotation.class) == null);// false  
19   }  

其中第17行输出为false,证明在Child类上找到了MyAnnotation这个注解,这是因为MyAnnotation上有Inheried的注解,所以当在Child类上没有找到时会去Child类的父类Parent上找这个注解。

如果将第2行Inheried从MyAnnotation上去掉,则第17行会输出true,证明在Child类上没有找到MyAnnotation的注解。

内置注解-Native

变量

用法

  1. 只能用于成员变量或枚举类型上;
  2. 标示这个成员变量或枚举类型可能被native的代码所引用;

内置注解-Repeatable

变量

注解类

用法

  1. 只能用于其他注解上;
  2. 用于标识被标识的注解可以重复使用在被标注对象上;
  3. 通过传入的变量来标注重复定义的注解如何来处理;
  4. JDK1.8中引入。

例子

@AnnotationExample.MyAnnotation("annotation1")
@AnnotationExample.MyAnnotation("annotation2")
public class AnnotationExample {  
    @Documented
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.TYPE)
    @Repeatable(MyAnnotations.class)
    public @interface MyAnnotation {
        String value() default "";
    }

    @Documented
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.TYPE)
    public @interface MyAnnotations {
        MyAnnotation[] value();
    }

    public static void main(String[] args) {
        System.out.println(AnnotationExample.class.getAnnotations().length);// 1
        System.out.println(AnnotationExample.class.getAnnotations()[0]);
    }
}

输出为:
1  
@com.oomlife.java.example.AnnotationExample$MyAnnotations(value=[@com.oomlife.java.example.AnnotationExample$MyAnnotation(value=annotation1), @com.oomlife.java.example.AnnotationExample$MyAnnotation(value=annotation2)])

如上所示,在MyAnnotation上被Repeatable标注后,MyAnnotation可以重复在一个地方使用多次。当多次使用时实际上是被Repeatable传入的MyAnnotations来处理的,如第一行的输出所示。

内置变量-Retention

变量

RetentionPolicy,包含以下类型:

Policy类型 含义

SOURCE

注解只被保留在源码中,在编译期会被抛弃

CLASS

注解在class中存在,但在运行期被抛弃

RUNTIME

注解在运行期也存在,可以通过反射获取

用法

  1. 只能用于其他注解上;
  2. 用于告诉编译器和JVM该注解需要在什么时候被抛弃;
  3. 如果没有声明则默认是CLASS;

内置变量-Target

变量

ElementType,包含以下类型:

类型 含义

TYPE

类、接口、枚举类

FIELD

成员变量或枚举类型

METHOD

方法

PARAMETER

方法参数

CONSTRUCTOR

构造方法

LOCAL_VARIABLE

局部变量

ANNOTATION_TYPE

注解

PACKAGE

package-info.java

TYPE_PARAMETER

类型参数

TYPE_USE

使用类型的地方

用法

  1. 只能用于其他注解上;
  2. 用于标识被标识的注解可以用在哪些地方;
  3. 如果没有声明则默认是所有地方;

例子

public class AnnotationExample {  
    @Documented
    @Inherited
    @Retention(RetentionPolicy.RUNTIME)
    @Target({
            ElementType.TYPE,
            ElementType.FIELD,
            ElementType.PARAMETER,
            ElementType.LOCAL_VARIABLE,
            ElementType.PACKAGE,
            ElementType.TYPE_PARAMETER,
            ElementType.TYPE_USE
    })
    public @interface MyAnnotation {
        String value() default "";
    }

    @MyAnnotation("parent class")// TYPE 用于class
    public static class Parent {
    }

    public <@MyAnnotation T> void get(T t) throws Exception {// TYPE_PARAMETER用于类型参数
        T newT = (@MyAnnotation T) t.getClass().newInstance();// TYPE_USE用于使用类型的地方
    }

    public static void main(@MyAnnotation String[] args) {// PARAMETER用于方法参数
        @MyAnnotation// LOCAL_VARIABLE用于局部变量
        String abc = "abc";
    }

    public enum MyEnum {
        @MyAnnotation// FIELD用于枚举类型
        enum1;
    }
}
分享按钮