Annotaions(一)------The Basis

 
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();
}
 
 
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值