zoukankan      html  css  js  c++  java
  • Java step by step(3): Annotation

    About Annotation

    Java 5引入了Annotation, 这极大减轻了开发的负担,不用写很多的代码,只需要在代码中加入一些"tag"就可以了,这个很符合声明式编程(declarative programming)的思想。

    当然有个问题还是要问的,虽然作为使用annotation的开发者来说,不用考虑Annotation最后究竟会被怎样执行,只要在需要使用Annotation的地方tag一下就可以,但是很显然这个只是把问题处理地点转移了而已,终归是需要有人来处理的,不然,这个Annotation就没有任何意义了。

    可以想见,很多JDK提供的annotation, JVM或者编译器肯定是要负责解释处理这些anntation的。如果使用一些framework提供的annotation, 自然这些framework会提供解释执行这些annotation的代码实现,否则JVM怎么可能知道如何去解释这些tag呢。那么究竟如何去识别代码中哪些地方使用了annotation呢,很容易想到可以运用reflection来实现。

    所以,annotation看起来很神秘,其实只是借助了reflection,将相关的代码实现处理逻辑封闭在一个地方,从而使得运用这些annoation的代码不需要重复实现这些功能,从而简化了工作量。

    The Rules of Defining Java Annotation Types

    // MyAnnotation.java
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.FIELD)
    public @interface MyAnnotation {
    public String doSomething() default "do something";
    public String date();
    }

    上面是一个简单的Annotation定义,Annotation的定义很特别,很像interface,不过需要在interface前面加个@符号。另外annotation中定义的method (attribute) 不能是private的,不能接受参数,不能有throws语句,返回值的类型必须是如下几种之一:

    1)primitives

    2)  String

    3)  Class

    4) Enum

    5) Array of the above types

    Java Annotation Types

    Java 支持两种Annotation类型:

    1) 简单类型:这种annotation只能用于其它code,不能用于annotation 类型。

    2)Meta Annotation: 这种annotation是用于annotation type的,也就是annotation of annotation.

    Out-of-the-box Simple Annotation Types in JDK

    JDK提供了3个简单类型的annotations, 包括:

    1) Override

    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.SOURCE)
    public @interface Override {
    }

      

    可以看到Override只能用于method, 而且retention级别是SOURCE。这个Annotation的好处在于可以帮助我们快速发现问题,如果把toString写成了toString1,编译器会给出错误提示,这样就不要等到运行的时候发现出错了。  


    2) Deprecated

    @Documented
    @Retention(RetentionPolicy.RUNTIME)
    public @interface Deprecated {
    }

     如果一个方法或者变量被标示成Deprecated,那就意味着该方法或者变量是不应该被使用的,否则的话,编译器会报出警告信息。 


    3) Suppresswarnings

    @Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
    @Retention(RetentionPolicy.SOURCE)
    public @interface SuppressWarnings {
    /**
    * The set of warnings that are to be suppressed by the compiler in the
    * annotated element. Duplicate names are permitted. The second and
    * successive occurrences of a name are ignored. The presence of
    * unrecognized warning names is <i>not</i> an error: Compilers must
    * ignore any warning names they do not recognize. They are, however,
    * free to emit a warning if an annotation contains an unrecognized
    * warning name.
    *
    * <p>Compiler vendors should document the warning names they support in
    * conjunction with this annotation type. They are encouraged to cooperate
    * to ensure that the same names work across multiple compilers.
    */
    String[] value();
    }

    这个Annotation是让编译器忽略某些warning信息。  


    Out-of-the-box Meta Annotation Types in JDK

    JDK提供了如下4种Meta Annotation Types:

    1) Target

    @Documented
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.ANNOTATION_TYPE)
    public @interface Target {
    ElementType[] value();
    }

    这个Annotation用来标示定义的annotation类型可以用在哪些类型的元素上,包括如下几种....

    -- @Target(ElementType.TYPE)

    -- @Target(ElementType.FIELD) : public attributes of the class

    -- @Target(ElementType.METHOD)

    -- @Target(ElementType.PARAMETER)

    -- @Target(ElementType.CONSTRUCTOR)

    -- @Target(ElementType.LOCAL_VARIABLE)

    -- @Target(ElementType.ANNOTATION_TYPE)

     

    2) Retention

    @Documented
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.ANNOTATION_TYPE)
    public @interface Retention {
    RetentionPolicy value();
    }
      

    这个Annotation表示定义的annotation会retention的时间,有如下三种值:

    -- RententionPolicy.SOURCE: retained at the source level, ignored by the compiler

    -- RententionPolicy.CLASS: retained by the compiler, ignored by the VM

    -- RententionPolicy.RUNTIME: retained by the VM, can be read only at run-time.


    3) Documented

    @Documented
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.ANNOTATION_TYPE)
    public @interface Documented {
    }

    表示定义的annotation type应该被javadoc加入到生成的document中的。  


    4) Inherited

    /**
     * Indicates that an annotation type is automatically inherited.  If
     * an Inherited meta-annotation is present on an annotation type
     * declaration, and the user queries the annotation type on a class
     * declaration, and the class declaration has no annotation for this type,
     * then the class's superclass will automatically be queried for the
     * annotation type.  This process will be repeated until an annotation for this
     * type is found, or the top of the class hierarchy (Object)
     * is reached.  If no superclass has an annotation for this type, then
     * the query will indicate that the class in question has no such annotation.
     *
     * <p>Note that this meta-annotation type has no effect if the annotated
     * type is used to annotate anything other than a class.  Note also
     * that this meta-annotation only causes annotations to be inherited
     * from superclasses; annotations on implemented interfaces have no
     * effect.
     *
     * @author  Joshua Bloch
     * @since 1.5
     */
    @Documented
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.ANNOTATION_TYPE)
    public @interface Inherited {
    }

    A Simple Example

    定义一个简单的Annotation Type -- MyAnnoation

    // MyAnnotation.java
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.FIELD)
    public @interface MyAnnotation {
    public String doSomething() default "do something";
    public String date();
    }

      

    通过Reflection来获取annotation定义的field...

    // MainTest.java
    public class MainTest {

    @MyAnnotation(doSomething
    = "Test Annotation", date = "2011-08-01")
    public String annotationTest;

    public void testAnnotation() {
    Class aClass
    = MainTest.class;
    try {
    Field aField
    = aClass.getField("annotationTest");
    MyAnnotation myAnnotation
    = aField.getAnnotation(MyAnnotation.class);

    annotationTest
    = myAnnotation.doSomething() + " on " + myAnnotation.date();
    System.out.println(
    this.annotationTest);
    }
    catch (SecurityException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    catch (NoSuchFieldException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }


    }
    /**
    *
    @param args
    */
    public static void main(String[] args) {
    new MainTest().testAnnotation();
    }

    }

      

      

  • 相关阅读:
    (C#) 设定时间格式
    (WPF) MVVM: 动态添加控件及绑定。
    (WPF) MVVM: DataGrid Binding
    (WPF) MVVM: ComboBox Binding, XML 序列化
    (C#) 判断相等?
    ASP.NET MVC过滤器中权限过滤器ValidateAntiForgeryToken的用法(Post-Only)
    根据2个经纬度点,计算这2个经纬度点之间的距离
    ASP.NET导出Excel(利用NPOI和EPPlus库,无需安装Office)
    nopcommerce 二次开发
    SQL效率低下原因主要有
  • 原文地址:https://www.cnblogs.com/fangwenyu/p/2124310.html
Copyright © 2011-2022 走看看