Java Annotations

Java Annotations是什么

  • Annontation是Java5开始引入的新特征。中文名称一般叫注解。它提供了一种安全的类似注释的机制,用来将任何的信息或元数据(metadata)与程序元素(类、方法、成员变量等)进行关联。
  • 更通俗的意思是为程序的元素(类、方法、成员变量)加上更直观更明了的说明,这些说明信息是与程序的业务逻辑无关,并且是供指定的工具或框架使用的。
  • Annontation像一种修饰符一样,应用于包、类型、构造方法、方法、成员变量、参数及本地变量的声明语句中。

简单示例

  • 下面通过一个简单的例子来看一下Java Annotations 的用法。例子里面有两个Annotations定义,一个使用Annotations的类。一个解析Annotations的类。

Annotations定义1:一个面向类型的说明

package annoation.test;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * Created by haicheng.lhc on 04/07/2017.
 *
 * @author haicheng.lhc
 * @date 2017/07/04
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
public @interface Description {
    String value();
}

Annotations定义12:一个面向方法的说明

package annoation.test;

import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.annotation.ElementType;


/**
 * Created by haicheng.lhc on 04/07/2017.
 *
 * @author haicheng.lhc
 * @date 2017/07/04
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Documented
public @interface Author {

    String name();
    String group();
}

使用Annotations的类

package annoation.test;

/**
 * Created by haicheng.lhc on 04/07/2017.
 *
 * @author haicheng.lhc
 * @date 2017/07/04
 */
@Description(value = "这是一个有用的类")
public class Utility {
    @Author(name = "haoran_202",group="com.magc")
    public String work() {
        return "work over!";
    }
}

解析Annotations的类

package annoation.test;

import java.lang.reflect.Method;

/**
 * Created by haicheng.lhc on 04/07/2017.
 *
 * @author haicheng.lhc
 * @date 2017/07/04
 */
public class AnalysisAnnotation {

    public static void main(String[] args) {

        try {
            //通过运行时反射API获得annotation信息
            Class rt_class = Class.forName("annoation.test.Utility");
            Method[] methods = rt_class.getMethods();

            boolean flag = rt_class.isAnnotationPresent(Description.class);

            if (flag) {
                Description description = (Description)rt_class.getAnnotation(Description.class);
                System.out.println("Utility's Description--->" + description.value());
                for (Method method : methods) {
                    if (method.isAnnotationPresent(Author.class)) {
                        Author author = (Author)method.getAnnotation(Author.class);
                        System.out.println("Utility's Author--->" + author.name() + " from " + author.group());

                    }
                }
            }

        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

    }
}

输出结果

深入分析

Annotation 组成

每一个Annotation有三部分组成:

Java Annotations_第1张图片
  • 1、Annotation.java

定义中的@Interface就代表该类继承了Annotation

package java.lang.annotation;
public interface Annotation {

    boolean equals(Object obj);

    int hashCode();

    String toString();

    Class annotationType();
}
  • 2、ElementType.java
package java.lang.annotation;

public enum ElementType {
    TYPE,               /* 类、接口(包括注释类型)或枚举声明  */

    FIELD,              /* 字段声明(包括枚举常量)  */

    METHOD,             /* 方法声明  */

    PARAMETER,          /* 参数声明  */

    CONSTRUCTOR,        /* 构造方法声明  */

    LOCAL_VARIABLE,     /* 局部变量声明  */

    ANNOTATION_TYPE,    /* 注释类型声明  */

    PACKAGE             /* 包声明  */
}
  • 3、RetentionPolicy.java
package java.lang.annotation;
public enum RetentionPolicy {
    SOURCE,            /* Annotation信息仅存在于编译器处理期间,编译器处理完之后就没有该Annotation信息了  */

    CLASS,             /* 编译器将Annotation存储于类对应的.class文件中。默认行为  */

    RUNTIME            /* 编译器将Annotation存储于class文件中,并且可由JVM读入 */
}

如何定义

  • Annotation类型使用关键字@interface而不是interface,这个关键字声明隐含了一个信息:它是继承了java.lang.annotation.Annotation接口,并非声明了一个interface

  • Annotation类型、方法定义是独特的、受限制的

1、Annotation 类型的方法必须声明为无参数、无异常抛出的。
2、这些方法定义了annotation的成员:方法名成为了成员名,而方法返回值成为了成员的类型。
3、而方法返回值类型必须为primitive类型、Class类型、枚举类型、annotation类型或者由前面类型之一作为元素的一维数组。
4、方法的后面可以使用 default和一个默认数值来声明成员的默认值,null不能作为成员默认值,这与我们在非annotation类型中定义方法有很大不同。
5、Annotation类型和它的方法不能使用annotation类型的参数、成员不能是generic。
6、只有返回值类型是Class的方法可以在annotation类型中使用generic,因为此方法能够用类转换将各种类型转换为Class。

你可能感兴趣的:(Java Annotations)