一、Annotation高级特性
java.lang.annotation.Retention型态可以在您定义Annotation型态时,指示编译程序该如何对待您的自定义的Annotation型态
预设上编译程序会将Annotation信息留在.class档案中,但不被虚拟机读取,而仅用于编译程序或工具程序运行时提供信息
在使用Retention型态时,需要提供java.lang.annotation.RetentionPolicy的枚举型态
package java.lang.annotation;
public enumRetentionPolicy
{
SOURCE, //编译程序处理完Annotation信息后就完成任务
CLASS, //编译程序将Annotation储存于class当中,缺省
RUNTIME //编译程序将Annotation储存于class当中,可由VM读入
}
RetentionPolicy为SOURCE的例子是@SuppressWarnings
仅在编译时期告知编译程序来抑制警告,所以不必将这个信息储存于.class档案
RetentionPolicy为RUNTIME的时,可以用Java设计一个程序代码,让JVM读出Annotation信息,以便在分析程序时使用,搭配反射(Reflection)机制,就可以达到这个目的。
java.lang.annotation.AnnotatedElement接口
public Annotation getAnnotation(Class annotationType);
public Annotation[] getAnnotations();
public Annotation[] getDeclaredAnnotations();
public booleanisAnnotationPresent(Class annotationType);
Class、Constructor、Field、Method、Package等类别,都实现了AnnotatedElement接口
参见程序实例
package com.cienet.advanced;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface RetentionAnnotation {
String hello() default "cienet";
String world();
}
package com.cienet.advanced;
public class RetentionClass {
@RetentionAnnotation(world = "shanghai")
// @Deprecated
// @SuppressWarnings("unchecked")
public void output() {
System.out.println("output something");
}
}
package com.cienet.advanced;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
public class RetentionAnnotationTest {
public static void main(String[] args) throws Exception {
Class<RetentionClass> myTest = RetentionClass.class;
Method method = myTest.getMethod("output", new Class[]{});
if (method.isAnnotationPresent(RetentionAnnotation.class)) {
RetentionAnnotation annotationTest = method.getAnnotation(RetentionAnnotation.class);
String hello = annotationTest.hello();
String world = annotationTest.world();
System.out.println(hello);
System.out.println(world);
}
// Annotation[] annotations = method.getAnnotations();
// for (Annotation annotation : annotations) {
// System.out.println(annotation.annotationType().getName());
// }
}
}
@Target
表示该注解用于什么地方,可能的参数由java.lang.annotation.ElementType决定。
package java.lang.annotation;
public enumElementType
{
TYPE, //适用class,interface, enum
FIELD, //适用field
METHOD, //适用method
PARAMETER, //适用method上之parameter
CONSTRUCTOR, //适用constructor
LOCAL_VARIABLE, //适用局部变量
ANNOTATION_TYPE, //适用annotation型态
PACKAGE //适用package
}
参见范例
package com.cienet.advanced;
public class TargetClass {
@TargetAnnotation("xyz")
public void doSomething() {
System.out.println("hello world");
}
}
package com.cienet.advanced;
import java.lang.annotation.Target;
import java.lang.annotation.ElementType;
//@Target(ElementType.TYPE)
public @interface TargetAnnotation {
String value();
}
@Documented
这个annotation非常简单,也非常容易理解,使用过javadoc命令的人都会很清楚,我们可以用javadoc命令将方法,类,变量等前面的注释转换成文档,在默认的情况下javadoc命令不会将我们的annotation生成到doc中去的,所以使用该标记就是告诉jdk让它也将annotation生成到doc中去。
参见程序实例
package com.cienet.advanced;
import java.lang.annotation.Documented;
//@Documented
public @interface DocumentedAnnotation {
String hello();
}
package com.cienet.advanced;
public class DocuemntedAnnotationTest {
@DocumentedAnnotation(hello = "welcome")
public void method() {
System.out.println("test document");
}
}
@Inherited
预设上父类别中的Annotation并不会被继承至子类别中可以在定义Annotation型态时加上@Inherited使注解能继承到子类中。
JDK的文档提到@Inherited只能放在类上,本人测试发现放在方法上也是可以的。
注意:该注解放在方法上的时候子类重写父类方法时该注解会被覆盖掉。
参见程序实例
package com.cienet.advanced;
import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface InheritedAnnotation {
String value();
}
package com.cienet.advanced;
import java.lang.reflect.Method;
public class InheritedAnnotationTest {
public static void main(String[] args) throws Exception{
Class<Child> childClass = Child.class;
if (childClass.isAnnotationPresent(InheritedAnnotation.class)) {
InheritedAnnotation inheritedAnnotation = childClass.getAnnotation(InheritedAnnotation.class);
String value = inheritedAnnotation.value();
System.out.println(value);
}
// Method method = childClass.getMethod("doSomething", new Class[]{});
// if (method.isAnnotationPresent(InheritedAnnotation.class)) {
// InheritedAnnotation inheritedAnnotation = method.getAnnotation(InheritedAnnotation.class);
// String value = inheritedAnnotation.value();
// System.out.println(value);
// }
}
}
二、APT