JAVA [ Annotation]

来源:互联网 发布:keep软件的用法 编辑:程序博客网 时间:2024/05/21 16:20
Annotation是继承自java.lang.annotation.Annotation的类,用于向程序分析工具或虚拟机提供package class field methed 等方面的信息,它和其他类没什么区别,除了使用方式. 

     Annotation的一般形式是 :

public @interface MyAnnotation {
    String value() default "hahaha";

等价于:

public class MyAnnotation extends java.lang.annotation.Annotation{
     private String value = "hahaha";
     public void setValue(String value){
          this.value = value;
     }
     public String getValue(){
          return value;
      }
}

 Annotation的使用方法和Bean的比较: 

@MyAnnotation(value="hello")     //对应Bean的set方法
Method method = AnnotationTest.class.getMethod("doSomthing", null);   //取得被注释的方法,AnnotationTest.class为该方法所在的类
MyRetention mr = method.getAnnotation(MyRetention.class); //取得注释对象
String value = mr.value();    //取得value的值,对应Bean的get方法.

 @interface实际上是继承了java.lang.annotation.Annotation,所以定义annotation时不能继承其他annotation或interface. 
    java.lang.annotation.Retention告诉编译器如何对待 Annotation,使用Retention时,需要提供java.lang.annotation.RetentionPolicy的枚举值.

public enum RetentionPolicy {
    SOURCE, // 编译器处理完Annotation后不存储在class中
    CLASS, // 编译器把Annotation存储在class中,这是默认值
    RUNTIME // 编译器把Annotation存储在class中,可以由虚拟机读取,反射需要

java.lang.annotation.Target告诉编译器Annotation使用在哪些地方,使用需要指定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

 java.lang.annotation.Documented用于指定该Annotation是否可以写入javadoc中. 
java.lang.annotation.Inherited用于指定该Annotation用于父类时是否能够被子类继承. 

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Documented  //这个Annotation可以被写入javadoc
@Inherited       //这个Annotation 可以被继承
@Target({ElementType.CONSTRUCTOR,ElementType.METHOD}) //表示这个Annotation只能用于注释 构造子和方法
@Retention(RetentionPolicy.CLASS) //表示这个Annotation存入class但vm不读取
public @interface MyAnnotation {
String value() default "hahaha";
}

java.lang.reflect.AnnotatedElement接口提供了四个方法来访问Annotation

public Annotation getAnnotation(Class annotationType);
public Annotation[] getAnnotations();
public Annotation[] getDeclaredAnnotations();
public boolean isAnnotationPresent(Class annotationType);

Class、Constructor、Field、Method、Package等都实现了该接口,可以通过这些方法访问Annotation信息,前提是要访问的Annotation指定Retention为RUNTIME. 

    Java内置的annotation有Override Deprecated SuppressWarnings. 
    Override只用于方法,它指明注释的方法重写父类的方法,如果不是,则编译器报错. 
    Deprecated指明该方法不建议使用 
    SuppressWarnings告诉编译器:我知道我的代码没问题,你不用吓我了,我不怕的^_^ 



*********************************************************************

/**
 * 用户自定义标签,带有成员变量的MyTag
 */
@Documented //将注释包含在JavaDoc中
@Inherited //允许子类继承父类中的注释。
@Target(value = {ElementType.METHOD,ElementType.CONSTRUCTOR})//标注这个注释使用的范围
@Retention(value = RetentionPolicy.RUNTIME)//要想使用反射得到注释信息,这个注释必须使用


public @interface MyTag {

String name()  default "shenjie";//给自定义注释类的成员加上默认值
int age()  default 24;
}

————————————————————————————————————————————

/**
 * @author SHEN Jie
 */
public class TagTest {

//完整注释
@MyTag(name = "MyTag", age = 1)
public void test() {
}


//标记注释
@Override //可以保证编译时候Override函数的声明正确性
public String toString() {
return super.toString();
}


//单一值注释
@Deprecated //对不应再使用的方法进行注解
public String notToUse() {
return super.toString();
}

public static void main(String[] args) throws Exception, ClassNotFoundException {

TagTest tt = new TagTest();
Annotation[] annotations;

//-----------------------
try {
annotations = tt.getClass().getMethod("test")
.getAnnotations();
for (Annotation tag : annotations) {
System.out.println("Tag is: " + tag);
System.out.println("tag.name(): " + ((MyTag) tag).name());
System.out.println("tag.age(): " + ((MyTag) (tag)).age());
}
} catch (NoSuchMethodException e) {
e.printStackTrace();
}

int passed = 0, failed = 0;
//被检测的类名
String className="annotation.TagTest";
for (Method m : Class.forName(className).getMethods()) {
if (m.isAnnotationPresent(MyTag.class)) {
System.out.println(m.getName());
try{
m.invoke(tt);
passed++;
}catch(Exception ex){
System.out.printf("测试 %s 失败: %s %n", m, ex.getCause());
System.out.println( ex.getMessage());
failed++;
}
}
}
System.out.printf("测试结果: 通过: %d, 失败: %d%n", passed, failed);
}
}

原创粉丝点击