标签:
什么是注解?【代码1】
@Override public String toString() { return "This is String Representation of current object."; }上面的代码中,我重写了toString()方法并使用了@Override注解。但是,即使我不使用@Override注解标记代码,程序也能够正常执行。那么,该注解表示什么?这么写有什么好处吗?事实上,@Override告诉编译器这个方法是一个重写方法(描述方法的元数据),如果父类中不存在该方法,编译器便会报错,提示该方法没有重写父类中的方法。如果我不小心拼写错误,例如将toString()写成了toStrring(){double r},而且我也没有使用@Override注解,那程序依然能编译运行。但运行结果会和我期望的大不相同。现在我们了解了什么是注解,并且使用注解有助于阅读程序。
注解 |
说明
|
@Override
|
当我们想要复写父类中的方法时,我们需要使用该注解去告知编译器我们想要复写这个方法。这样一来当父类中的方法移除或者发生更改时编译器将提示错误信息。 |
@Deprecated
|
当我们希望编译器知道某一方法不建议使用时,我们应该使用这个注解。Java在javadoc 中推荐使用该注解,我们应该提供为什么该方法不推荐使用以及替代的方法。 |
@SuppressWarnings
|
这个仅仅是告诉编译器忽略特定的警告信息,例如在泛型中使用原生数据类型。它的保留策略是SOURCE(译者注:在源文件中有效)并且被编译器丢弃。
|
@SafeVarargs
|
修饰”堆污染”警告
|
@FunctionalInterface
|
Java8特有的函数式接口
|
元注解 |
释义
|
@Retention
|
指明了该Annotation被保留的时间长短。RetentionPolicy取值为SOURCE,CLASS,RUNTIME。
|
@Target
|
指明该类型的注解可以注解的程序元素的范围。该元注解的取值可以为(ElementType.)TYPE,METHOD,CONSTRUCTOR,FIELD,PARAMETER,LOCAL_VARIABLE,ANNOTATION_TYPE,PACKAGE。如果Target元注解没有出现,那么定义的注解可以应用于程序的任何元素。
|
@Documented
|
指明拥有这个注解的元素可以被javadoc此类的工具文档化。这种类型应该用于注解那些影响客户使用带注释的元素声明的类型。如果一种声明使用Documented进行注解,这种类型的注解被作为被标注的程序成员的公共API。
|
@Inherited
|
指明该注解类型被自动继承。如果用户在当前类中查询这个元注解类型并且当前类的声明中不包含这个元注解类型,那么也将自动查询当前类的父类是否存在Inherited元注解,这个动作将被重复执行知道这个标注类型被找到,或者是查询到顶层的父类。
|
package annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Inherited @Target({ElementType.ANNOTATION_TYPE, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) public @interface Testable { }【代码3】
@Testable class SupperClass { } class SubClass extends SupperClass { public SubClass() { for(Annotation annotation:SubClass.class.getAnnotations()) { System.out.println(annotation); } for(Annotation annotation:SubClass.class.getDeclaredAnnotations()) { System.out.println("getDeclaredAnnotations:"+annotation); } } }【代码4】
package annotation; import java.lang.annotation.Annotation; import org.junit.Test; public class Client { @Test public void Client() { new SubClass(); } }运行结果:@annotation.Testable()
package annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Inherited @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.METHOD,ElementType.TYPE}) public @interface Tag { String name() default "zzh"; String description() default "excellent!"; }注解元素必须有确定的值,要么在定义注解的默认值中指定,要么在使用注解时指定,非基本类型的注解元素的值不可为null。因此, 使用空字符串或0作为默认值是一种常用的做法。这个约束使得处理器很难表现一个元素的存在或缺失的状态,因为每个注解的声明中,所有元素都存在,并且都具有相应的值,为了绕开这个约束,我们只能定义一些特殊的值,例如空字符串或者负数,一次表示某个元素不存在,在定义注解时,这已经成为一个习惯用法。
package java.lang.annotation; public interface Annotation { boolean equals(Object obj); int hashCode(); String toString(); Class<? extends Annotation> annotationType(); }提取Annotation信息
修饰符与类型
|
方法与描述
|
<T extends Annotation> T
|
getAnnotation(类<T> annotationClass)
Returns this element‘s annotation for the specified type if such an annotation is present, else null.
|
Annotation[]
|
getAnnotations()
Returns all annotations present on this element.
|
Annotation[]
|
getDeclaredAnnotations()
Returns all annotations that are directly present on this element.
|
boolean
|
isAnnotationPresent(类<?
extends Annotation> annotationClass)
Returns true if an annotation for the specified type is present on this element, else false.
|
package annotation; import java.lang.annotation.Annotation; import org.junit.Test; public class Client { @Test public void client() throws NoSuchMethodException, SecurityException { Annotation[] annotations = this.getClass().getMethod("client").getAnnotations(); for(Annotation annotation : annotations) { System.out.println(annotation.annotationType().getName()); } } }运行结果:org.junit.Test
package annotation; import java.lang.annotation.Annotation; import org.junit.Test; @Tag(name="hiddenzzh") public class Client { @Test public void client() throws NoSuchMethodException, SecurityException { Annotation[] annotations = this.getClass().getAnnotations(); for(Annotation annotation : annotations) { if(annotation instanceof Tag) { Tag tag = (Tag)annotation; System.out.println("name:"+tag.name()); System.out.println("description:"+tag.description()); } } } }运行结果:
package annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Inherited @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface Testable { }【代码10】
package annotation; import java.io.IOException; public class TestCase { @Testable public void test1() { System.out.println("test1"); } public void test2() throws IOException { System.out.println("test2"); throw new IOException("我test2出错啦..."); } @Testable public void test3() { System.out.println("test3"); throw new RuntimeException("我test3出错啦..."); } public void test4() { System.out.println("test4"); } @Testable public void test5() { System.out.println("test5"); } @Testable public void test6() { System.out.println("test6"); } }【代码11】
package annotation; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; public class TestableProcessor { public static void process(String className) throws InstantiationException, IllegalAccessException, ClassNotFoundException { int passed = 0; int failed = 0; Object obj = Class.forName(className).newInstance(); for(Method method:Class.forName(className).getMethods()) { if(method.isAnnotationPresent(Testable.class)) { try { method.invoke(obj, null); ++passed; } catch(IllegalAccessException | InvocationTargetException e) { System.out.println("method "+method.getName()+" execute error:< "+e.getCause()+" >"); e.printStackTrace(System.out); ++failed; } } } System.out.println("共运行 "+(failed+passed)+"个方法,成功:"+passed+"个"); } public static void main(String[] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException { process("annotation.TestCase"); } }运行结果:
test1 test3 method test3 execute error:< java.lang.RuntimeException: 我test3出错啦... > java.lang.reflect.InvocationTargetException at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.lang.reflect.Method.invoke(Unknown Source) at annotation.TestableProcessor.process(TestableProcessor.java:19) at annotation.TestableProcessor.main(TestableProcessor.java:36) Caused by: java.lang.RuntimeException: 我test3出错啦... at annotation.TestCase.test3(TestCase.java:21) ... 6 more test5 test6 共运行 4个方法,成功:3个注意到在TestCase中只有test1,test3,test5以及test6标注了@Testable的注解,通过注解处理器TestableProcessor进行处理,只运行了这个四个标注注解的方法,这个就是通过注解来实现junit功能的一个雏形。
元注解 |
释义
|
@Retention
|
指明了该Annotation被保留的时间长短。RetentionPolicy取值为SOURCE,CLASS,RUNTIME。
|
@Target
|
指明该类型的注解可以注解的程序元素的范围。该元注解的取值可以为(ElementType.)TYPE,METHOD,CONSTRUCTOR,FIELD,PARAMETER,LOCAL_VARIABLE,ANNOTATION_TYPE,PACKAGE。如果Target元注解没有出现,那么定义的注解可以应用于程序的任何元素。
|
@Documented
|
指明拥有这个注解的元素可以被javadoc此类的工具文档化。这种类型应该用于注解那些影响客户使用带注释的元素声明的类型。如果一种声明使用Documented进行注解,这种类型的注解被作为被标注的程序成员的公共API。
|
@Inherited
|
指明该注解类型被自动继承。如果用户在当前类中查询这个元注解类型并且当前类的声明中不包含这个元注解类型,那么也将自动查询当前类的父类是否存在Inherited元注解,这个动作将被重复执行知道这个标注类型被找到,或者是查询到顶层的父类。
|
标签:
原文地址:http://blog.csdn.net/u013256816/article/details/50592685