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有三部分组成:
- 1、Annotation.java
定义中的@Interface就代表该类继承了Annotation
package java.lang.annotation;
public interface Annotation {
boolean equals(Object obj);
int hashCode();
String toString();
Class<? extends Annotation> 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。