Java注解

注解理解

      注释是为了向以后阅读这份代码的人解释说明一些事情,注解是注释的升级版,它可以向编译器、虚拟机等解释说明一些事情。

      注解是描述Java代码的代码,它能够被编译器解析,注解处理工具在运行时也能够解析注解。

     注解比java注释和Javadoc要强大得多,它们三者之间的重大的区别在于,Java注释和Javadoc描述所发挥的作用仅仅到编译时就止步了,而注解直到运行时都能够发挥作用。

     注解为我们提供了为类/方法/属性/变量添加描述信息的更通用的方式,而这些描述信息对于开发者、自动化工具、Java编译器和Java运行时来说都是有意义的,也就是说他们都能“读懂”注解信息。
     除了传递信息,我们也可以使用注解生成代码。我们可以使用注解,然后让注解解析工具来解析它们,以此来生成一些”模板化“的代码。

 

注解的分类

根据注解参数的个数,我们可以将注解分为三类:
    1.标记注解:一个没有成员定义的Annotation类型被称为标记注解。这种Annotation类型仅使用自身的存在与否来为我们提供信息。比如后面的系统注解@Override;
    2.单值注解
    3.完整注解  

  根据注解使用方法和用途,我们可以将Annotation分为三类:
    1.JDK内置系统注解
    2.元注解
    3.自定义注解

  

元注解

     元注解即用来描述注解的注解

    

Docemented

      当一个注解类型被@Documented元注解所描述时,那么无论在哪里使用这个注解,都会被Javadoc工具文档化。我们来看一下它的定义:

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Documented {
}

定义注解使用@interface关键字
这个元注解被@Documented修饰,表示它本身也会被文档化。 @Retention元注解的值RetentionPolicy.RUNTIME表示@Documented这个注解能保留到运行时;@Target元注解的值ElementType.ANNOTATION_TYPE表示@Documented这个注解只能够用来描述注解类型。 

Inherited

  表明被修饰的注解类型是自动继承的。具体解释如下:若一个注解类型被Inherited元注解所修饰,则当用户在一个类声明中查询该注解类型时,若发现这个类声明中不包含这个注解类型,则会自动在这个类的父类中查询相应的注解类型,这个过程会被重复,直到该注解类型被找到或是查找完了Object类还未找到。这个元注解的定义如下:

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
    public @interface Inherited {
}

这个元注解类型被@Documented所注解,能够保留到运行时,只能用来描述注解类型。

Retention

  它表示一个注解类型会被保留到什么时候,比如以下代码表示Developer注解会被保留到运行时:

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
    /**
     * Returns the retention policy.
     * @return the retention policy
     */
    RetentionPolicy value();
}

我们在使用@Retention时,后面括号里的内容即表示他的取值,从以上定义我们可以看到,取值的类型为RetentionPolicy,这是一个枚举类型,它可以取以下值:
* SOURCE:表示在编译时这个注解会被移除,不会包含在编译后产生的class文件中;
* CLASS:表示这个注解会被包含在class文件中,但在运行时会被移除;
* RUNTIME:表示这个注解会被保留到运行时,在运行时可以JVM访问到,我们可以在运行时通过反射解析这个注解。

Target

  这个元注解说明了被修饰的注解的应用范围,也就是被修饰的注解可以用来注解哪些程序元素,它的定义如下:

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
    /**
     * Returns an array of the kinds of elements an annotation type
     * can be applied to.
     * @return an array of the kinds of elements an annotation type
     * can be applied to
     */
    ElementType[] value();
}

看到它也会保留到运行时,而且它的取值是为ElementType[]类型(一个数组,意思是可以指定多个值),ElementType是一个枚举类型,它可以取以下值:

  • TYPE:表示可以用来注解类、接口、注解类型或枚举类型;
  • PACKAGE:可以用来注解包;
  • PARAMETER:可以用来注解参数;
  • ANNOTATION_TYPE:可以用来注解 注解类型;
  • METHOD:可以用来注解方法;
  • FIELD:可以用来注解属性(包括枚举常量);
  • CONSTRUCTOR:可以用来注解构造器;
  • LOCAL_VARIABLE:可用来注解局部变量。

自定义注解

       自定义的注解需要解析工具来解析。注解的定义接近接口形式。

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Documented
public @interface AliasFor {

    /**
     * Alias for {@link #attribute}.
     * <p>Intended to be used instead of {@link #attribute} when {@link #annotation}
     * is not declared &mdash; for example: {@code @AliasFor("value")} instead of
     * {@code @AliasFor(attribute = "value")}.
     */
    @AliasFor("attribute")
    String value() default "";

    /**
     * The name of the attribute that <em>this</em> attribute is an alias for.
     * @see #value
     */
    @AliasFor("value")
    String attribute() default "";

    /**
     * The type of annotation in which the aliased {@link #attribute} is declared.
     * <p>Defaults to {@link Annotation}, implying that the aliased attribute is
     * declared in the same annotation as <em>this</em> attribute.
     */
    Class<? extends Annotation> annotation() default Annotation.class;

}

在定义注释时的注意事项:

       注解类型是通过 @interface关键字定义的

       在”注解体“中,所有的方法均没有方法体且只允许public和abstract这两种修饰符号(不加修饰符缺省为public),注解方法不允许有throws子句;

       注解方法的返回值只能为以下几种:原始数据类型), String, Class, 枚举类型, 注解和它们的一维数组,可以为方法指定默认返回值。

       注解之中只能声明方法,不能声明字段。

使用注解:

       给注解传值,给指定的注解方法传值需要指定注解方法名。

通过反射来提取注解:

       java.lang.reflect.AnnotatedElement 注解元素

            已知实现类:

                    Class, Method, Filed, Constructor, Package

      可以提供此接口实现类注解的完美提取。

原文地址:https://www.cnblogs.com/hengwu/p/9716881.html