• 限定重写父类方法:@Override

作用是告诉编译器检查这个方法,保证父类要包含一个被该方法重写的方法,否则就会编译出错。

  • 标记已过时:@Deprecated

用于表示某个程序元素(类或方法)已过时,当其他程序使用已过时的类或方法时,编译器会给出警告。

  • 抑制编译器警告:@SuppressWarnings

指示被该Annotation修饰的程序元素取消显示指定的编译器警告。@SuppressWarnings会一直作用于该程序元素的所有子元素。

通常情况下,如果程序中使用没有泛型限制的集合将会引起编译器警告,为了避免这种编译器警告,可以使用@SuppressWarnings修饰。@SuppressWarnings(value="unchecked")

 

用于修饰Annotation的Annotation

  • @Retention

只能用于修饰一个Annotation定义,用于指定被修饰的Annotation可以保留多长时间。

@Retention(value = RetentionPolicy.RUNTIME)
public @interface Testable()

或者也可以省略value

@Retention(RetentionPolicy.SOURCE)
public @interface Testable()

表示Testable这个Annotation只保留在源码中,编译器会直接丢弃Retention为SOURCE的Annotation

  • @Target

指定被修饰的Annotation能用于修饰哪些程序单元,如constructor,field,method,怕人阿meter,package等。

@Target(ElementType.Field)
public @interface ActionListenerFor()
  • @Documented

用于指定Annotation类将被javadoc工具提取成文档,如果定义Annotation类时使用了@Documented修饰,则所有使用该Annotation修饰的程序元素的API文档中将会包含该Annotation说明。

  • @Inherited

指定被它修饰的Annotation将具有继承性----如果某个类使用了@A Annotation(A annotation使用了@Inherited修饰)修饰,则其子类将自动被@A 修饰。

 

  • 自定义Annotation

定义新的Annotation类型使用@interface关键字,默认情况下,Annotation可用于修饰任何程序元素,包括类,接口,方法等。

public @interface Test {
}

自定义Annotation也可以带成员变量,成员声明和接口方法声明类似,成员的声明有以下几点限制:

  1. 成员以无入参无抛出异常的方式声明,如boolean value(String str)/boolean value() throws Exception等都是非法的。
  2. 可以通过default为成员指定一个默认值,当然也可以不指定。
  3. 成员类型是受限的,合法的类型包括基本类型及其包装类型,String,Class,enums和注解类型以及上述类型的数组类型。自定义类型是不允许的。

如果注解只有一个成员,则成员名必须取名为value(),在使用时可以忽略成员名和赋值号(=),如@NeedTest(true).注解类拥有多个成员时,如果仅对value成员进行赋值则也可以不使用赋值号,如果同时对多个成员进行赋值,则必须使用赋值号。注解类可以没有成员,没有成员的注解成为标识注解。

public @interface MyTag {
    String name() default "ivy";
    int age() default 18;
}
public class Test {
    @MyTag(name="xx", age=6)
    public void info() {
    }
}

当开发者使用Annotation修饰了类,方法,Field等成员后,这些Annotation不会自己生效,必须有开发者提供相应的工具来提取并处理Annotation信息。

Annotation[] aArray = Calss.forName("Test").getMethod("info").getAnnotations();
for(Annotation an : aArray) {
    if (an instanceof MyTag1) {
    System.out.println("tag.name():" + ((MyTag1)tag).method1());
  }
  if (an instanceof MyTag2) {
    System.out.println("tag.name():" + ((MyTag2)tag).method1());
  }
}

Example:

package com.ivy.annotation;

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

@Retention(RetentionPolicy.RUNTIME)
@Target(value={METHOD})
public @interface Testable {

}
package com.ivy.annotation;

public class MyTest{

    @Testable
    public static void m1(){
        
    }
    
    public static void m2(){
            
    }
    @Testable
    public static void m3(){
        throw new RuntimeException("Boom");
    }
    
    public static void m4(){
        
    }
    
    @Testable
    public static void m5(){
        
    }
    
    public static void m6(){
        
    }
    @Testable
    public static void m7(){
        throw new RuntimeException("Crash");
    }
    
    public static void m8(){
        
    }
    

}
package com.ivy.annotation;

import java.lang.reflect.Method;

public class ProcessTest {
    public static void process(String clazz) throws SecurityException, ClassNotFoundException {
        int passed = 0;
        int failed = 0;
        
        for(Method m : Class.forName(clazz).getMethods()) {
            if (m.isAnnotationPresent(Testable.class)) {
                try {
                    m.invoke(null);
                    passed++;
                } catch (Exception ex) {
                    System.out.println("method" + m + "failed :" + ex.getCause());
                    failed++;
                }
            }
        }
        System.out.println("All run methods :" + (passed+failed) + "passed :" + passed + "failed: " + failed);
    }
}
package com.ivy.annotation;

public class RunTest {

    public static void main(String[] args) throws SecurityException, ClassNotFoundException {
        // TODO Auto-generated method stub
        ProcessTest.process("com.ivy.annotation.MyTest");
    }

}

注意:Class.forName(String className) 此处className必须是class全称,包含包名。

posted on 2017-02-14 09:36  coder为  阅读(224)  评论(0编辑  收藏  举报