测试技术交流群:161204772
悦分享测试联盟:136924235
悦分享论坛:bbs.shareku.com
一、Annotation 简介
java.lang.annotation
,接口 Annotation。对于Annotation,是Java5的新特性,JDK5引入了Metedata(元数据)很容易的就能够调用Annotations。Annotations提供一些本来不属于程序的数据,比如:一段代码的作者或者告诉
编译器
禁止一些特殊的错误。Annotation 对代码的执行没有什么影响。Annotations使用@annotation的形式应用于代码:类(class),属性(attribute),方法(method)等等。一个Annotation出现在上面提到的开始位置,而且一般只有一行,也可以包含有任意的参数。
二、
Annotation定义
如下:
只要是Annotation都必须实现此接口。
public interface Annotation {
public Class<? extends Annotation> annotationType();
public boolean equals(Object obj);
public int hashCode(); String toString();
}
三、系统内建的3个Anntation,用户可直接使用
@Override:覆写
@Deprecated :不赞成使用的
@SuppressWarnings :压制警告
关于3个Annotation的详细定义查看javadoc
四、自定义Anntation
格式如下:
public @interface 名称{
数据类型 变量名称();
}
annotation使用@interface标示,表明实现了Annotation接口,其中Anntation中可以定义变量,变量名称后边必须使用一对圆括号。
五、annotation的使用
public @Interface Demo{
public String value();
public String name();
public int age();
}
第一种:使用没有属性的Annotation
@Demo
public class TestDemo{
}
第二种:向Annotation中设置内容
@Demo("Ray")
class TestDemo{}
默认我们设置的内容“Ray”,会使用annotation中的value属性接受,且只有属性名为value时可以这样使用,另一种传递属性值的方式如下:
2、
向Annotation中传递多个值:
@Demo(value="Ray",name="venus",age="24")
class TestDemo{}
3、
给annotation定义数组属性
public @Interface Demo{
public String[] vaule();
}
3-1,、使用
@Demo(value={"ray","venus","jupiter"})
class TestDemo{}
第三种:使用属性默认值
Annotation定义
public @interface Demo{
String name() default "ray";
int age() default 24;
}
第四种:使用枚举设置内容
1、定义Name的enum类型
public enum Name{
Ray,Venus,Jupiter,Mercury;
}
2、再定义一个annotation,此annotation属性值必须从Name这个枚举中取得
public @interface Demo{
public Name name() default Name.Ray;//这里的默认值只能设置为enum中的内容
}
3、使用:
@Demo(name=Name.Venus)
class TestDemo{}
六、
Retention、RetentionPolicy
使用Retention定义一个Annotation的保存范围,此Annotation定义如下:
@Documented
@Retention(value=RUNTIME)
@Target(value=ANNOTATION_TYPE)
public @interface Retention{
RetentionPolicy value();
}
其中定义在Retention中的属性value 类型RetentionPolicy就是一个枚举,所以使用此Annotation时,设置内容必须从此枚举中取得。
该枚举中有三个值:SOURCE , CLASS , RUNTIME
SOURCE : 表明此Annotation信息只保存在源文件中,即 .java文件
CLASS : 表明此Annotation信息存在于源文件及编译后的class文件中 (默认)
RUNTIME : 表明此Annotation 信息存在于java ,class 文件中,且执行时会加载到JVM中
七、
Target
Target中传递的内容表明此Annotation应用的位置,默认情况,Annotation可以使用在任何地方,类,方法,属性等。
该Annotation定义如下:
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
ElementType[] value();
}
从定义可以看出,Target可以接收一组ElementType类型的数据,ElementType为枚举类型,定义如下:
public enum ElementType {
/** Class, interface (including annotation type), or enum declaration */
TYPE,
/** Field declaration (includes enum constants) */
FIELD,
/** Method declaration */
METHOD,
/** Parameter declaration */
PARAMETER,
/** Constructor declaration */
CONSTRUCTOR,
/** Local variable declaration */
LOCAL_VARIABLE,
/** Annotation type declaration */
ANNOTATION_TYPE,
/** Package declaration */
PACKAGE
}
八、
Retention 及 Target使用
@Retentiong(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE,ElementType.METHOD})
public @interface Demo{
}
此annotation 定义会出现在java,class文件及runtime中,且只能应用于类,接口 及 方法之上。
九、一个小demo 展示annotation如何应用于程序中,结合反射机制
1、定义annotation
package annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Demo {
public String value();
}
2、通过反射机制使annotation起作用
package annotation;
import java.lang.reflect.Method;
class TestDemo {
public static void main(String[] args) throws Exception {
Class<?> c = TestDemo.class;
Method m = c.getMethod("say", String.class);
Demo d = m.getAnnotation(Demo.class);
String value = d.value();
m.invoke(c.newInstance(), value);
}
@Demo("hello annotation")
public void say(String sentence) {
System.out.println(sentence);
}
}
总结:annotation定义与以往的类与接口定义略有差异,另外annotation中存在属性,没有方法定义,如果要让一个Annotation有意义,则
必须结合反射机制一起使用
对于测试使用来说junit中的annotation,我们只需要在理解annotation的工作原理之后,便能灵活应用junit,另外上一篇文章中我以代码示例
的方式描述了如何自定义annotation来限制测试方法的执行顺序,所以理解annotation结合反射工作机制是非常有必要的。