30、注解(Annotation)

注解也是jdk1.5的新特性

jdk内置注解

1、Java注解(Annotation):Override注解表示子类要重写(override)父类的对应方法。@Override

2、@Deprecated   表示方法是不建议被使用的

[java] view plain copy print ?
  1. public class DeprecatedTest 
  2.     @Deprecated 
  3.     public void <del>doSomething</del>() 
  4.     { 
  5.         System.out.println("do some thing"); 
  6.     } 
  7.      
  8.     public static void main(String[] args) 
  9.     { 
  10.         DeprecatedTest test = new DeprecatedTest(); 
  11.          
  12.         test.<del>doSomething</del>(); 
  13.     } 

3、@SuppressWarnings("unchecked")   注解表示抑制(压制)警告

4、Override、Deprecated注解都是Marker Annotation(标识性注解),注解名称本身即表示了要给工具程序的信息。

5、定义自己的注解:

[java] view plain copy print ?
  1. public @interface AnnotationTest 
  2.      
  3.  
  4.  
  5. @AnnotationTest 
  6. public class AnnotationUsage 
  7.     @AnnotationTest 
  8.     public void method() 
  9.     { 
  10.         System.out.println("dadsa"); 
  11.     } 
  12.      
  13.     public static void main(String[] args) 
  14.     { 
  15.         AnnotationUsage usage = new AnnotationUsage(); 
  16.         usage.method(); 
  17.     } 


定义注解使用@interface关键字,这里定义的相当于一个Marker Annotation

6、自定义注解带属性:

[java] view plain copy print ?
  1. public @interface AnnotationTest 
  2.     String value(); 
  3.  
  4.  
  5. @AnnotationTest(value="hello"
  6. public class AnnotationUsage 
  7.     @AnnotationTest("world"
  8.     public void method() 
  9.     { 
  10.         System.out.println("dadsa"); 
  11.     } 
  12.      
  13.     public static void main(String[] args) 
  14.     { 
  15.         AnnotationUsage usage = new AnnotationUsage(); 
  16.         usage.method(); 
  17.     } 


自定义注解:当注解中的属性名为value时,在对其赋值时可以不指定属性的名字而直接写上属性值即可;除了value以外的其他都需要使用name=value这种复制形式,明确指定给谁赋值。例如AnnotationTest中定义的是String value1();则使用注解时必须这样:@AnnotationTest(value1="hello")

定义属性时设置默认值:String value1() fefault "hello";

当我们使用@interface关键字定义一个注解时,该注解隐含的继承了java.lang.annotation.Annotation接口,;如果我们定义了一个接口,并且让该接口继承自Annotation,那么我们所定义的接口依然还是接口而不是注解;Annotation本身是接口类型而不是注解。可以与Enum类比。

[java] view plain copy print ?
  1. public @interface AnnotationTest 
  2.     String value1() default "hello"
  3.      
  4.     EnumTest value2(); 
  5.  
  6. enum EnumTest 
  7.     hello,world,welcome; 
  8.  
  9.  
  10. @AnnotationTest(value2=EnumTest.hello) 
  11. public class AnnotationUsage 
  12.     @AnnotationTest(value1="world",value2=EnumTest.world) 
  13.     public void method() 
  14.     { 
  15.         System.out.println("dadsa"); 
  16.     } 
  17.      
  18.     public static void main(String[] args) 
  19.     { 
  20.         AnnotationUsage usage = new AnnotationUsage(); 
  21.         usage.method(); 
  22.     } 


7、告知编译器如何处理@Retention

java.lang.annotation.Retention型态可以在你定义Annotation型态时,指示编译程序该如何对待你的自定义的Annotation型态,预设上编译程序会将Annotation信息留在.class档案中,但不被虚拟机读取,而仅用于编译程序或工具程序运行时提供信息。在使用Retention型态时,需要提供java.lang.annotation.RetentionPolicy的枚举类型,三种值:CLASS,RUNTIME,SOURCE。

当为RUNTIME时,可以通过反射机制读取。SuppressWarnings注解是SOURCE的

RetentionPolicy为RUNTIME的时机,可以像是你使用Java设计一个程序代码分析工具,你必须让VM能读出Annotation信息,以便在分析程序时使用,搭配反射(Reflection)机制,就可以达到这个目的。

java.lang.reflect.AnnotatedElement接口,提供了一些方法,来对注解进行操作。

[java] view plain copy print ?
  1. import java.lang.annotation.Retention; 
  2. import java.lang.annotation.RetentionPolicy; 
  3.  
  4. @Retention(RetentionPolicy.RUNTIME) 
  5. public @interface MyAnnotation 
  6.     String hello() default "shanghai"
  7.      
  8.     String world(); 
  9.  
  10. @MyAnnotation(hello="beijing",world = "tianjin"
  11. public class MyTest 
  12.     @MyAnnotation(hello = "tianjin",world ="ddd"
  13.     @Deprecated 
  14.     @SuppressWarnings("unchecked"
  15.     public void output() 
  16.     { 
  17.         System.out.println("mytest"); 
  18.     } 
  19.  
  20.  
  21. import java.lang.annotation.Annotation; 
  22. import java.lang.reflect.Method; 
  23.  
  24. public class MyReflection 
  25.     public static void main(String[] args) throws Exception 
  26.     { 
  27.         MyTest myTest = new MyTest(); 
  28.          
  29.         Class<MyTest> c = MyTest.class
  30.          
  31.         Method method = c.getMethod("output",new Class[]{}); 
  32.          
  33.         if(method.isAnnotationPresent(MyAnnotation.class)) 
  34.         { 
  35.             method.invoke(myTest,new Object[]{}); 
  36.              
  37.             MyAnnotation myAnnotation = method.getAnnotation(MyAnnotation.class); 
  38.              
  39.             String hello = myAnnotation.hello(); 
  40.             String world = myAnnotation.world(); 
  41.              
  42.             System.out.println(hello + "," + world); 
  43.         } 
  44.          
  45.         Annotation[] annotations = method.getAnnotations(); 
  46.          
  47.         for(Annotation annotation : annotations) 
  48.         { 
  49.             System.out.println(annotation.annotationType().getName()); 
  50.         } 
  51.     } 

8、限定annotation使用对象@Target

使用java.lang.annotation.Target可以定义其使用之时机(可以修饰哪些对象),在定义时要指定java.lang.annotation.ElementType的枚举值之一

ElementType的各个取值:TYPE:适用class,interface,enum;FIELD:适用field;METHOD:适用method;PARAMETER:适用method上的parameter;CONSTRUCTOR:适用constructor;LOCAL_VARIABLE:适用局部变量;ANNOTATION_TYPE:适用annotation类型;PAKAGE:适用package。

9、Documented注解:生成doc文档时注解出现

10、Inherited注解:注解是否会继承下来

11、注解在实际中的应用:JUnit单元测试(3.8版本,4.x版本):

对于3.8版本,继承TestCase,方法名以testXxx形式出现,反射得到所有方法,然后找到以test开头的方法,运行之。

对于4.x版本,使用注解加反射,JUnit4的执行的一般流程:

   A)首先获得待测试类所对应的Class对象

   B)然后通过该Class对象获得当前类中所有public方法所对应的Method数组。

   C)遍历该Method数组,取得每一个Method对象

   D)调用每个Method对象的isAnnotationPresent(Test.class)方法,判断该方法是否被Test注解所修饰。

   E)如果该方法返回true,那么调用method.invoke()方法去执行该方法。,否则不执行。

单元测试不是为了证明你是对的,而是证明没有错误。Input is evil

你可能感兴趣的:(java开发工具)