1.
Annotations
,即注释、注解。出现的形式为
Java源码中的标签(Tag),例如:Java文档相关的注释@author,@version,@link等,都是些Annotation。一般也称为Metadata。这些Annotation可以被一些工具读取并进行相关的处理,例如:JavaDoc可以读取@link并生成相应的HTML连接。
2.
通常,Annotation可以用于(
1)生成一些辅助性的文件,例如:根据EJB EntityBean中的Annotation自动生成Mapping XML文件等;(2)自动生成码,例如:自动生成测试、日志等代码,当然,这需要相应的apt(Annotation processing tools)工具支持;(3)也可以用于功能增强,例如:通过ASM或CGLI对注解类/方法修改达到功能增强的目的。
3.
java.lang.annotation.*
(1). Annotation
-
这是一个接口,所有的 Annotation类型都自动的为Annotation接口的子类。
-
需要注意的是:直接手工的方式通过 extends来继承本接口并不能定义一个Annotation类型;如果需要定义一个Annotation类型需要通过@interface来申明:
-
public @interface MyAnnotation {
-
-
}
-
Class<? extends Annotation> annotationType()方法:
-
用于获取当前 Annotation的类型。
-
String toString()方法:
-
返回当前 Annotation的字符形式,这个字串通常是实现相关的,但一般情况返回如下形式字串: @com.ibis.Name(first=ibis,last=wang)
(2). ElementType
它是一个
Enums类型常量。同Target meta-annotation一块使用,用于指定annotation可以使用的目标对象。
(3). RetentionPolicy
它是一个
Enums类型常量。同Retention meta-annotation一块使用,用于指定annotation保持力情况。
(4). Documented
作用于
annotation类型,用于定义一个Annotation,使得其作用的对象的JavaDoc文档中出现本Annotation.
(5). Interited
作用于annotation类型,用于指明当前annotation类型将自动被继承。如果一个类型有一个interited的annotation,那么,它的所有子类都将自动的有这个annotation。Class的annotation一般情况下是不会被子类继承的,即非这外annotation是interited的。
需要注意的是,interited annotation的继承属性仅对Class注解有效,对于interface,method, field, Constructor等无效
。也就是说,即便YourAnnotation在定义的时候定义为@Interited,如果在基类的方法或者field上使用YourAnnotation注解,那么子类中对应的方法上仍不可能取得YourAnnotation对象:例如:
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface InheritedAnno {
}
@InheritedAnno
public class BaseClass {
@InteritedAnno
public void info() {
}
}
public class SubClass extends BaseClass{
}
这样,你通过
SubClass.class.getAnnotations()可以得到InteritedAnno对象,但是你不可以通过SubClass#info()方法的getAnnotations()得到InteritedAnno,因为它不作用于除Class之外的对象。
(6). Retention
作用于annotation类型,用于指定定义的annotation的保持力。
通常在定义一个annotation时没有明确指定即是RetentionPolicy.CLASS。
Retetion的值通常有RetentionPloicy.SOURCE,RetentionPolicy.CLASS, RetentionPolicy.RUNTIME。
当Retention为SOURCE时,则当类编译为CLASS之后,CLASS文件就没有相应的注解数据了;当为CLASS时,CLASS文件中有,但是当JVM加载CLASS到内存中后,内存中的CLASS就没有注解数据了;当为RUNTIME时,在运行时,你也可以通过Reflection API获取相应的注解数据。
例如:
@Retention
(RetentionPolicy.
RUNTIME
)
public
@interface
AnnoRuntimeLevel
{
String value();
}
@Retention
(RetentionPolicy.
SOURCE
)
public
@interface
AnnoSourceLevel
{
String value();
}
public
@interface
AnnoClassLevel
{
String value();
}
public
class
TestAnnoLevel {
@AnnoSourceLevel
(
"source-method"
)
@AnnoClassLevel
(
"class-method"
)
@AnnoRuntimeLevel
(
"runtime-method"
)
public
String theTestMethod() {
return
"this is test method"
;
}
public
static
void
main(String[] args) {
Method[] methods = obj.getClass().getMethods();
for
(Method method : methods) {
out
.println(
"==="
+ method.toString()+
"=="
);
Annotation[] anos = ane.getAnnotations();
out
.println(
" ====getAnnotations()======="
);
for
(Annotation ano : anos) {
out
.println(
" "
+ ano.toString());
}
anos = ane.getDeclaredAnnotations();
out
.println(
"====getDeclaredAnns()===="
);
for
(Annotation ano : anos) {
out
.println(
" "
+ ano.toString());
}
}
}
}
你将只能得到@AnnoRuntimeLevel("runtime-method")的输出,不能得到@AnnoSourceLevel("source-method")与@AnnoSourceLevel("class-method")的输出。
(7).Target
作用于
annotation类型,用于指定定义的annotation能够作用的目标对象。主要的目标对象有:ANNOTATION_TYPE, CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACAGE, PARAMETER, TYPE. 它们定义在ElementType Enum对象中。
使用方式:
@Target({})----—只能用于复合的
Annotation内部。
@Target({ElementType.FIELD, ElementType.METHOD})----代表作用于
Method与Field对象。
如果没有指定
Target,则表明可以出现在所在的对象中。
例如:
@Target({})
public @interface InnerAnno {
}
如下使用方式是不能通过编译的:
@InnerAnno
public class MyTestInner {
}
但你可以定义如下
annotation:
public @interface MyAnno {
InnerAnno demo();
}
然后如下使用:
@MyAnno(demo=@InnerAnno)
public class MyTestInner {
}
4.
定义方式:
import java.lang.annotation.*;
modifiers @interface AnnotationName {
type elementName1();
type elementName2() default theDefaultValue;
… …
type elementNameN();
}
例如:
import java.lang.annotation.*;
public @interface TransactionAnnotation {
String name() default “default”;
}
@Document
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.Method})
public @interface MyMethodAnnotation {
String firstElement() default “firstElement”
int secondELement() default 0;
TransactionAnnotation transaction();
}
5.
注解方式:
使用
annotation的方式很简单,例如上面的MyMethodAnnotation的定义中分别使用Document, Interited, Retention等annotation,其形式一般如下:
@AnnotationName(elementName1=value1, elementName2=value2,…)
例如:
public class MyClass {
………
@MyMethodAnnotation(firstElement=”abc”,transaction=@TransactionAnnotation(name=”default”))
public boolean save() {
………
}
}
当一个
annotation只有一个element时,通常我们将其命名为value,例如:
public @interface SimpleAnnotation {
String value() default “[None]”;
}
这样在使用其进行
annotation时可以进行简单表达:
@SimpleAnnotation(“Just A Value”)
在使用
Annotation进行注解没有指定相关element的值时,如果element有缺省值则取其缺省值,如果没有缺省值,则compiler会报错。所以annotation element的值不可以为null,即便是在指定缺省值时也不可以指定为null值。
6.
annotation element
的取值:
annotation element的值不可以是
null值(即便是在设定缺省值时)。
Annotation element的类型只能是如下类型:
- 基本类型(int,short,long,byte,char,double,float,boolean)
- String
- Class(可以带<? extends AnyClass>参数)
- enum
- Annotation 类型
- 上面类型的数型
但是数组的数组是不支持的。
例如如下是一个有效的
Annotation定义:
public @interface DeveloperAnnotation {
enum Level {PRIMARY, SENIOR, CHIEF};
boolean hasContract() default true;
String[] name() default {“first”, “last”};
Class<? extends Human> ImplementClass() default Human.class;
Level level() default Level.PRIMARY;
AnotherAnnotationType another();
}