JavaSE基础—Annotation(注解)

来源:互联网 发布:淘宝代收驿站 编辑:程序博客网 时间:2024/05/16 09:49

一、OverView

        注解在JavaSE中属于一种高级的用法,在项目以及很多的框架结构中都使用到了注解这种特殊用法,注解是在JDK1.5之后的一个新特性。在我们开始编写Java代码的时候,经常会在代码中生成@Override(重写) @Deprecated(f废弃的) @SuppressWarnings(压缩警告),这是在JDK1.5之后提供的常用注解。
        
        首先来一段小的Code,预热一下。

      public class Demo{public static void main(String[] args) {     funDeprecated();}@Deprecatedpublic static void funDeprecated(){    System.out.println("这是一个过期的方法");}public Thread createThread() {  return new Thread(new Runnable() {  @Override   public void run() {      System.out.println("这是一个重写的方法");   } });}@SuppressWarnings({ "unused", "resource" })public void readFile(String path) throws FileNotFoundException{  File f = new File(path);//unused一个   InputStream stream = new FileInputStream(path);//unused resource两个 }     }


       
       在很多博客及书籍的地方有的将Annotation称为“注释”,其实是不对的,注释和注解是两个完全不同的概念,注解具有非常浓重的“Code”色彩,这个特性是注释完全不能表达的。注释给编程、测试人员看的,而注解有一部分是面向程序员的,但是更多的是面向于编译器的。注解简单的讲就是一种标记方式,在程序的特定的方式打上标记,这样编译器等工具就可以在相应的位置进行处理。注解可以标记在package , class , field , method , parameter , local variable之上。

二、Meta Annotation

        元注解(Meta Annotation)是注解的注解,就是在定义注解的时候使用的注解,用来控制自定义注解的最作用对象,生命周期等特性。

       2.1 @Retention

        Java在编译的过程中主要经理了3个阶段:
        (1) 编程人员编写得到java源代码(.java)                        -------------------------》RetentionPolicy.SOURCE
        (2) 使用javac将java源代码编译成为.class文件             -------------------------》RetentionPolicy.CLASS
        (3) JVM将class文件解释成为字节码文件(0,1组合的二进制)  -----------------》RetentionPolicy.RUNTIME

        RetentionPolicy.RUNTIME可以让你从JVM中读取Annotation注解的相关信息,以便在程序分析的时候使用。

        上述的三个值对应了java程序对应的三个阶段,当为自定义注解添加了对应的生命周期后,一旦对应的java阶段完成之后就会将该注解去掉。例如:加入一个注解添加了@Retention(RetentionPolicy.RUNTIME) 这样的注解,那么在编译成class文件之后该注解就去掉了。
        在JAVA中常见的三种注解 @Override @SuppressWarnings的生命周期是SOURCE , @Deprecated的生命周期是RUNTIME

       2.2 @Target

         Target可以控制自定义注解的作用对象,如field method等。使用方法为:
         @Target(ElementType.FIELD)
         
         Tips:如果注解中有value属性而且你在使用它,那么可以省略value =****,直接写属性值,就像上面@Target一样,也就是上述注解的完整写法是:
          @Target(value = ElementType.FIELD)

三、Instruction

       3.1 注解的定义

          注解的定义格式和类十分相似,也有对应的属性,具体的语法格式为:
          
           元注解
           public @interface  注解名{
                   属性定义[默认值]
           }       


          eg:

          @Retention(Retentionpolicy.SOURCE) 
          @Target({ElementType.METHOD,ElementType.Field})
          public @interface DemoAnnotation{
                 String classPath();     //注意属性定义的时候有一个括号
                 int endIndex() default 10; //为属性添加一个默认值
          }

       3.2 注解的使用和获取

        注解的使用和元注解一样,注解的获取通过相应类的class对象的getAnnotation方法获得。
        
@DemoAnnotation(classPath="com.test.mycode.impl.UserAction")
       public class Demo{
    
       public static void main(String[] args)
       {
        DemoAnnotation annotation = (DemoAnnotation)Demo.getClass().getAnnotation(DemoAnnotation.class);
        System.out.println(annotation.classPath);
        System.out.println(annotation.endIndex);

}

}
       

       3.3 注解属性的一些扩展

        注解的属性除了常规的int float String等类型外,我们还可以定义一些其他类型,如数组、枚举类型等。
        数组:
            String[] name()   default {"AAA","BBB","CCC"}   使用的时候  @DemoAnnotation(name ={"aaa","bbb","ccc"})
            SexType sex()    default SexType.Male     其中SexType是一个枚举类型


四、Demo

       下面是一些综合练习
package com.test.mycode.main;/** * 描述任务的优先级 * */public enum PriorityStatus {HIGH,MEDIUM,LOW}

package com.test.mycode.main;/** *  * 设置一个元注解 * */public @interface MetaAnnotation {String value();}

package com.test.mycode.main;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;@Retention(RetentionPolicy.RUNTIME)@Target({ElementType.METHOD, ElementType.TYPE})public @interface TaskAnnotation {String classPath();String value();    int[] arrayCode() default {1,2,3};    PriorityStatus status() default PriorityStatus.HIGH;    MetaAnnotation annotation() default @MetaAnnotation("mytask");}

package com.test.mycode.main;@TaskAnnotation(classPath="com.test.mycode.MyTest",value = "MyTest",    arrayCode = {4,2,8},    status = PriorityStatus.HIGH,    annotation = @MetaAnnotation("mytask"))public class MyTest {public static void main(String[] args) {if(MyTest.class.isAnnotationPresent(TaskAnnotation.class)) {//判断是否有该类型的注解//得到注解TaskAnnotation taskAnnotation = (TaskAnnotation)MyTest.class.getAnnotation(TaskAnnotation.class);System.out.println(taskAnnotation.classPath());System.out.println(taskAnnotation.value());System.out.println(taskAnnotation.arrayCode());System.out.println(taskAnnotation.status());System.out.println(taskAnnotation.annotation().value());}}}





0 0