annotation参数
1 告知编译器如何处理annotation @Retention
java.lang.annotation.Retention类型可以在您定义Annotation类型时,指示编译器该如何对待自定
义的Annotation类型,编译器默认会将Annotation信息留在.class文件中,但不被虚拟机读取,而仅用
于编译器或工具程序运行时提供信息。
在使用Retention类型时,需要提供java.lang.annotation.RetentionPolicy的枚举类型。
RetentionPolicy的定义如下所示:
package java.lang.annotation;
public enum RetentionPolicy{
SOURCE,//编译器处理完Annotation信息后就没有事了
CLASS,//编译器将Annotation存储于class文件中,默认
RUNTIME //编译器将Annotation存储于class文件中,可由VM读入
}
RetentionPolicy为SOURCE的例子是@SuppressWarnings,这个信息的作用仅在编译时期告知
编译器来抑制警告,所以不必将这个信息存储在.class文件中。
RetentionPolicy为RUNTIME的时机,可以像是您使用Java设计一个程序代码分析工具,您必须让VM能读出
Annotation信息,以便在分析程序时使用,搭配反射机制,就可以达到这个目的。
2 限定annotation使用对象 @Target
在定义Annotation类型时,使用java.lang.annotation.Target可以定义其适用的时机,在定义时要指定
java.lang.annotation.ElementType的枚举值之一。
public enum elementType{
TYPE,//适用class,interface,enum
FIELD,//适用于field
METHOD,//适用于method
PARAMETER,//适用method上之parameter
CONSTRUCTOR,//适用constructor
LOCAL_VARIABLE,//适用于区域变量
ANNOTATION_TYPE,//适用于annotation类型
PACKAGE,//适用于package
}
举例,假设定义Annotation类型时,要限定它只能适用于构造函数与方法成员,则:
package onlyfun.caterpillar;
import java.lang.annotation.Target;
import java.lang.annotation.ElementType;
@Target({ElementType.CONSTRUCTOR,ElementType.METHOD})
public @interface MethodAnnotation{}
将MethodAnnotation标示于方法之上,如:
public class SomeoneClass{
@onlyfun.caterpillar.MethodAnnotation
public void doSomething(){
......
}
}
3 要求为API文件的一部分 @Documented
在制作Java Doc文件时,并不会默认将Annotation的数据加入到文件中.Annnotation用于标示程序代码以便
分析工具使用相关信息,有时Annotation包括了重要的信息,您也许会想要在用户制作Java Doc文件的同时,
也一并将Annotation的信息加入到API文件中。所以在定义Annotation类型时,可以使用
java.lang.annotation.Documented.例:
package onlyfun.caterpillar;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Documented
@Retention(RetentionPolicy.RUNTIME)
public @interface TwoAnnotation{}
使用java.lang.annotation.Documented为定义的Annotation类型加上Annotation时,必须同时使用Retention
来指定编译器将信息加入.class文件,并可以由VM读取,也就是要设置RetentionPolicy为RUNTIME。接着可以使
用这个Annotation,并产生Java Doc文件,这样可以看到文件中包括了@TwoAnnotation的信息.
4 子类是否可以继承父类的annotation @Inherited
在定义Annotation类型并使用于程序代码上后,默认父类中的Annotation并不会被继承到子类中。可以在定义
Annotation类型时加上java.lang.annotation.Inherited类型的Annotation,这让您定义的Annotation类型在
被继承后仍可以保留至子类中。
例:
package onlyfun.caterpillar;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Inherited;
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface ThreeAnnotation{
String value();
String name();
}
可以在下面的程序中使用@ThreeAnnotation:
public class SomeoneClass{
@onlyfun.caterpillar.ThreeAnnotation(
value = "unit",
name = "debug1"
)
public void doSomething(){
.....
}
}
一下 是 定义各种参数 的annotation
无参数
package test; import java.lang.annotation.*; @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface NoParam { }
一个参数
package test; public @interface OneParam { String value(); }
多个参数
package test;
import java.lang.annotation.*; @Retention(RetentionPolicy.RUNTIME) public @interface MinultValue { String name(); String password(); }
数组类型参数package test;
public @interface ArrayParam { String[] value(); }
枚举类型参数
package test; public @interface EnumParam { enum enumTest { SPRING, SUMMER, AUMMANT, WINNER }; enumTest value(); }
缺省类型参数package test;
public @interface DefaultParam { String value() default "abc"; }
使用时候的代码
package test; import test.EnumParam.enumTest; import demo.*; @Description("fuck") public class test { @NoParam public void noParam() { System.out.println("noparam"); } @OneParam("this is one param") public void oneParam() { System.out.println("oneparam"); } @ArrayParam({ "param1", "param2" }) public void arrayParam() { System.out.println("arrayparam"); } @DefaultParam() public void defualtParam() { System.out.println("defaultparam"); } @EnumParam(value = enumTest.SPRING) public void enumParam() { System.out.println("enumparam"); } @MinultValue(name = "min", password = "param") public void minultParam() { System.out.println("minultparam"); } public static void main(String[] args) { test t = new test(); t.noParam(); t.oneParam(); t.arrayParam(); t.defualtParam(); t.enumParam(); t.minultParam(); } }
最关键的是如何操作annotation,主要是通过反射的方式处理annotation
package test;
import java.lang.reflect.*;
import demo.*;
public class AnsisyTest {
public static void main(String[] args) {
try {
Class<?> c = Class.forName("test.test");
Method[] methods = c.getMethods();
boolean flag = c.isAnnotationPresent(Description.class);
if (flag) {
Description des = (Description) c.getAnnotation(Description.class);
System.out.println("description:" + des.value());
}
for (Method m : methods) {
if (m.isAnnotationPresent(MinultValue.class)) {//定义的annotation 的@Retention(RetentionPolicy.RUNTIME)为运行时,才能在反射的时候使用,
MinultValue mv = m.getAnnotation(MinultValue.class);
System.out.println(mv.name());
System.out.println(mv.password());
}
}
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}