zoukankan      html  css  js  c++  java
  • 转:Java Annotation详解

    转载自:http://william750214.javaeye.com/blog/298104

    元数据的作用

    如果要对于元数据的作用进行分类,目前还没有明确的定义,不过我们可以根据它所起的作用,大致可分为三类:

    l         编写文档:通过代码里标识的元数据生成文档。

    l         代码分析:通过代码里标识的元数据对代码进行分析。

    l         编译检查:通过代码里标识的元数据让编译器能实现基本的编译检查。

     

    基本内置注释

        @Override注释能实现编译时检查,你可以为你的方法添加该注释,以声明该方法是用于覆盖父类中的方法。如果该方法不是覆盖父类的方法,将会在编译时报错。例如我们为某类重写toString()方法却写成了tostring(),并且我们为该方法添加了@Override注释;

         @Deprecated的作用是对不应该在使用的方法添加注释,当编程人员使用这些方法时,将会在编译时显示提示信息,它与javadoc里的@deprecated标记有相同的功能,准确的说,它还不如javadoc @deprecated,因为它不支持参数,

    注意:要了解详细信息,请使用 -Xlint:deprecation 重新编译。

        @SuppressWarnings与前两个注释有所不同,你需要添加一个参数才能正确使用,这些参数值都是已经定义好了的,我们选择性的使用就好了,参数如下:

     

    deprecation   使用了过时的类或方法时的警告

    unchecked  执行了未检查的转换时的警告,例如当使用集合时没有用泛型 (Generics) 来指定集合保存的类型

    fallthrough   当 Switch 程序块直接通往下一种情况而没有 Break 时的警告

    path   在类路径、源文件路径等中有不存在的路径时的警告

    serial 当在可序列化的类上缺少 serialVersionUID 定义时的警告

    finally    任何 finally 子句不能正常完成时的警告

    all 关于以上所有情况的警告

     

    注意:要了解详细信息,请使用 -Xlint:unchecked 重新编译。

     

    定制注释类型

        好的,让我们创建一个自己的注释类型(annotation type)吧。它类似于新创建一个接口类文件,但为了区分,我们需要将它声明为@interface,如下例:

    public @interface NewAnnotation {

     

    }

     

    使用定制的注释类型

        我们已经成功地创建好一个注释类型NewAnnotation,现在让我们来尝试使用它吧,如果你还记得本文的第一部分,那你应该知道他是一个标记注释,使用也很容易,如下例:

    public class AnnotationTest {

     

        @NewAnnotation

        public static void main(String[] args) {

     

        }

    }

     

    添加变量

        J2SE 5.0里,我们了解到内置注释@SuppressWarnings()是可以使用参数的,那么自定义注释能不能定义参数个数和类型呢?答案是当然可以,但参数类型只允许为基本类型、String、Class、枚举类型等,并且参数不能为空。我们来扩展NewAnnotation,为之添加一个String类型的参数,示例代码如下:

    public @interface NewAnnotation {

     

        String value();

    }

        使用该注释的代码如下:正如你所看到的,该注释的使用有两种写法,这也是在之前的文章里所提到过的。如果你忘了这是怎么回事,那就再去翻翻吧。

    public class AnnotationTest {

     

        @NewAnnotation("Just a Test.")

        public static void main(String[] args) {

            sayHello();

        }

     

        @NewAnnotation(value="Hello NUMEN.")

        public static void sayHello() {

            // do something

        }

    }

     

    为变量赋默认值

        我们对Java自定义注释的了解正在不断的增多,不过我们还需要更过,在该条目里我们将了解到如何为变量设置默认值,我们再对NewAnnotaion进行修改,看看它会变成什么样子,不仅参数多了几个,连类名也变了。但还是很容易理解的,我们先定义一个枚举类型,然后将参数设置为该枚举类型,并赋予默认值。

    public @interface Greeting {

     

        public enum FontColor {RED, GREEN, BLUE};

     

        String name();

     

        String content();

     

        FontColor fontColor() default FontColor.BLUE;

    }

     

    限定注释使用范围

        当我们的自定义注释不断的增多也比较复杂时,就会导致有些开发人员使用错误,主要表现在不该使用该注释的地方使用。为此,Java提供了一个ElementType枚举类型来控制每个注释的使用范围,比如说某些注释只能用于普通方法,而不能用于构造函数等。下面是Java定义的ElementType枚举:

    package java.lang.annotation;

     

    public enum ElementType {

      TYPE,         // Class, interface, or enum (but not annotation)

      FIELD,        // Field (including enumerated values)

      METHOD,       // Method (does not include constructors)

      PARAMETER,        // Method parameter

      CONSTRUCTOR,      // Constructor

      LOCAL_VARIABLE,   // Local variable or catch clause

      ANNOTATION_TYPE,  // Annotation Types (meta-annotations)

      PACKAGE       // Java package

    }

        下面我们来修改Greeting注释,为之添加限定范围的语句,这里我们称它为目标(Target)使用方法也很简单,如下:

     

    @Target( { ElementType.METHOD, ElementType.CONSTRUCTOR })

    public @interface Greeting {

    }

    正如上面代码所展示的,我们只允许Greeting注释标注在普通方法和构造函数上,使用在包申明、类名等时,会提示错误信息。

     

    注释保持性策略

    public enum RetentionPolicy {

      SOURCE,// Annotation is discarded by the compiler

      CLASS,// Annotation is stored in the class file, but ignored by the VM

      RUNTIME// Annotation is stored in the class file and read by the VM

    }

        RetentionPolicy的使用方法与ElementType类似,简单代码示例如下:

    @Retention(RetentionPolicy.RUNTIME)

    @Target( { ElementType.METHOD, ElementType.CONSTRUCTOR })

     

    文档化功能

        Java提供的Documented元注释跟Javadoc的作用是差不多的,其实它存在的好处是开发人员可以定制Javadoc不支持的文档属性,并在开发中应用。它的使用跟前两个也是一样的,简单代码示例如下:

    @Documented

    @Retention(RetentionPolicy.RUNTIME)

    @Target( { ElementType.METHOD, ElementType.CONSTRUCTOR })

    public @interface Greeting {

    }

     

    值得大家注意的是,如果你要使用@Documented元注释,你就得为该注释设置RetentionPolicy.RUNTIME保持性策略。为什么这样做,应该比较容易理解,这里就不提了。

     标注继承

     

    继承应该是Java提供的最复杂的一个元注释了,它的作用是控制注释是否会影响到子类,简单代码示例如下:

    @Inherited

    @Documented

    @Retention(RetentionPolicy.RUNTIME)

    @Target( { ElementType.METHOD, ElementType.CONSTRUCTOR })

    public @interface Greeting {

    }

     

    读取注释信息

        当我们想读取某个注释信息时,我们是在运行时通过反射来实现的,如果你对元注释还有点印象,那你应该记得我们需要将保持性策略设置为RUNTIME,也就是说只有注释标记了@Retention(RetentionPolicy.RUNTIME)的,我们才能通过反射来获得相关信息,下面的例子我们将沿用前面几篇文章中出现的代码,并实现读取AnnotationTest类所有方法标记的注释并打印到控制台。好了,我们来看看是如何实现的吧:

    public class AnnotationIntro {

     

        public static void main(String[] args) throws Exception {

     

            Method[] methods = Class.forName(

                    "com.gelc.annotation.demo.customize.AnnotationTest")

                    .getDeclaredMethods();

            Annotation[] annotations;

     

            for (Method method : methods) {

                annotations = method.getAnnotations();

                for (Annotation annotation : annotations) {

                    System.out.println(method.getName() + " : "

                            + annotation.annotationType().getName());

                }

     

     

     

    Java并发编程中,用到了一些专门为并发编程准备的 Annotation。 主要包括三类: 1、类 Annotation(注解) 就像名字一样,这些注解是针对类的。主有要以下三个: @Immutable @ThreadSafe @NotThreadSafe

    @ThreadSafe 是表示这个类是线程安全的。具体是否真安全,那要看实现者怎么实现的了,反正打上这个标签只是表示一下。不线程安全的类打上这个注解也没事儿。 @Immutable 表示,类是不可变的,包含了 @ThreadSafe 的意思。       @NotThreadSafe 表示这个类不是线程安全的。如果是线程安全的非要打上这个注解,那也不会报错。

    这三个注解,对用户和维护者是有益的,用户可以立即看出来这个类是否是线程安全的,维护者则是可以根据这个注解,重点检查线程安全方面。另外,代码分析工具可能会利用这个注解。

    2、域 Annotation(注解) 域注解是对类里面成员变量加的注解。 3、方法 Annotation(注解) 方法注解是对类里面方法加的注解。

    域注解和方法注解都是用@GuardedBy( lock )来标识。里面的Lock是告诉维护者:这个状态变量,这个方法被哪个锁保护着。这样可以强烈的提示类的维护者注意这里。

    @GuardedBy( lock )有以下几种使用形式:

    1、@GuardedBy( "this" ) 受对象内部锁保护 2、@GuardedBy( "fieldName" ) 受 与fieldName引用相关联的锁 保护。 3、@GuardedBy( "ClassName.fieldName" ) 受 一个类的静态field的锁 保存。 4、@GuardedBy( "methodName()" ) 锁对象是 methodName() 方法的返值,受这个锁保护。 5、@GuardedBy( "ClassName.class" ) 受 ClassName类的直接锁对象保护。而不是这个类的某个实例的锁对象。

  • 相关阅读:
    hdu 4002 Find the maximum
    hdu 2837 坑题。
    hdu 3123
    zoj Treasure Hunt IV
    hdu 2053 Switch Game 水题一枚,鉴定完毕
    poj 1430 Binary Stirling Numbers
    hdu 3037 Saving Beans
    hdu 3944 dp?
    南阳oj 求N!的二进制表示最低位的1的位置(从右向左数)。
    fzu 2171 防守阵地 II
  • 原文地址:https://www.cnblogs.com/wangorg/p/4123568.html
Copyright © 2011-2022 走看看