- 限定重写父类方法:@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也可以带成员变量,成员声明和接口方法声明类似,成员的声明有以下几点限制:
- 成员以无入参无抛出异常的方式声明,如boolean value(String str)/boolean value() throws Exception等都是非法的。
- 可以通过default为成员指定一个默认值,当然也可以不指定。
- 成员类型是受限的,合法的类型包括基本类型及其包装类型,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全称,包含包名。