Java 注释(Annotation)

发布日期:2019-09-05 17:02:00 阅读数: 456次 来源:亚博手机app

亚博手机app-
					Java 注释(Annotation)又称 Java 标注,是 JDK5.0 引入的一种正文机制。

<p>Java 言语中的类、方式、变量、参数和包等都能够被标注。和 Javadoc 分歧,Java 标注能够通过反射获取标注内容。在编译器生成类文件时,标注能够被嵌入到字节码中。Java 虚拟机能够保留标注内容,在运转时能够获取到标注内容 。 当然它也支撑自定义 Java 标注。</p>
<p>网上良多关于 Java Annotation 的文章,看得人目炫狼籍。Java Annotation 本来很简单的,成果说的人没说清晰;弄的看的人愈加含混。</p>

<p>我按照本身的思绪,对 Annotation 进行了拾掇。理解 Annotation 的环节,是理解 Annotation 的语法和用法,对这些内容,我都进行了细致申明;理解 Annotation 的语法和用法之后,再看 Annotation 的框架图,可能有更深刻体味。废话就说这么多,下面起头对 Annotation 进行申明。若您发觉文章中具有错误或不足的处所,但愿您能指出!</p>

<h3>内置的注释</h3>
<p>Java 定义了一套注释,共有 7 个,3 个在 java.lang 中,剩下 4 个在 java.lang.annotation 中。</p>

<p>感化在代码的注释是</p>
<ul><li>
<a href=亚博手机app@Override - 查抄该方式能否是重载方式。若是发觉其父类,或者是援用的接口中并没有该方式时,会报编译错误。

  • @Deprecated - 标识表记标帜过时方式。若是利用该方式,会报编译警告。
  • @SuppressWarnings - 指示编译器去忽略注释中声明的警告。
  • 感化在其他注释的注释(或者说 元注释)是:

    • @Retention - 标识这个注释怎样保留,是只在代码中,仍是编入class文件中,或者是在运转时能够通过反射拜候。
    • @Documented - 标识表记标帜这些注释能否包含在用户文档中。
    • @Target - 标识表记标帜这个注释该当是哪种 Java 成员。
    • @Inherited - 标识表记标帜这个注释是承继于哪个注释类(默认 注释并没有承继于任何子类)

    从 Java 7 起头,额外添加了 3 个注释:

    • @SafeVarargs - Java 7 起头支撑,忽略任何利用参数为泛型变量的方式或机关函数挪用发生的警告。
    • @FunctionalInterface - Java 8 起头支撑,标识一个匿名函数或函数式接口。
    • @Repeatable - Java 8 起头支撑,标识某注释能够在统一个声明上利用多次。

    1、Annotation 架构

    从中,我们能够看出:

    (01) 1 个 Annotation 和 1 个 RetentionPolicy 联系关系。

    能够理解为:每1个Annotation对象,城市有独一的RetentionPolicy属性。

    (02) 1 个 Annotation 和 1~n 个 ElementType 联系关系。

    能够理解为:对于每 1 个 Annotation 对象,能够有若干个 ElementType 属性。

    (03) Annotation 有很多实现类,包罗:Deprecated, Documented, Inherited, Override 等等。

    Annotation 的每一个实现类,都 "和 1 个 RetentionPolicy 联系关系" 而且 " 和 1~n 个 ElementType 联系关系"。

    下面,我先引见框架图的左半边(如下图),即 Annotation, RetentionPolicy, ElementType;然后在就 Annotation 的实现类进行举例申明。


    2、Annotation 构成部门

    java Annotation 的构成中,有 3 个很是主要的主干类。它们别离是:

    Annotation.java

    package java.lang.annotation;
    public interface Annotation {

        boolean equals(Object obj);

        int hashCode();

        String toString();

        Class<? extends Annotation> annotationType();
    }

    ElementType.java

    package java.lang.annotation;

    public enum ElementType {
        TYPE,               /* 类、接口(包罗正文类型)或列举声明  */

        FIELD,              /* 字段声明(包罗列举常量)  */

        METHOD,             /* 方式声明  */

        PARAMETER,          /* 参数声明  */

        CONSTRUCTOR,        /* 机关方式声明  */

        LOCAL_VARIABLE,     /* 局部变量声明  */

        ANNOTATION_TYPE,    /* 正文类型声明  */

        PACKAGE             /* 包声明  */
    }

    RetentionPolicy.java

    package java.lang.annotation;
    public enum RetentionPolicy {
        SOURCE,            /* Annotation消息仅具有于编译器处置期间,编译器处置完之后就没有该Annotation消息了  */

        CLASS,             /* 编译器将Annotation存储于类对应的.class文件中。默认行为  */

        RUNTIME            /* 编译器将Annotation存储于class文件中,而且可由JVM读入 */
    }

    申明:

    (01) Annotation 就是个接口。

    "每 1 个 Annotation" 都与 "1 个 RetentionPolicy" 联系关系,而且与 "1~n 个 ElementType" 联系关系。能够通俗的理解为:每 1 个 Annotation 对象,城市有独一的 RetentionPolicy 属性;至于 ElementType 属性,则有 1~n 个。

    (02) ElementType 是 Enum 列举类型,它用来指定 Annotation 的类型。

    "每 1 个 Annotation" 都与 "1~n 个 ElementType" 联系关系。当 Annotation 与某个 ElementType 联系关系时,就意味着:Annotation有了某种用处。例如,若一个 Annotation 对象是 METHOD 类型,则该 Annotation 只能用来润色方式。

    (03) RetentionPolicy 是 Enum 列举类型,它用来指定 Annotation 的策略。通俗点说,就是分歧 RetentionPolicy 类型的 Annotation 的感化域分歧。

    "每 1 个 Annotation" 都与 "1 个 RetentionPolicy" 联系关系。

    • a) 若 Annotation 的类型为 SOURCE,则意味着:Annotation 仅具有于编译器处置期间,编译器处置完之后,该 Annotation 就没用了。 例如," @Override" 标记就是一个 Annotation。当它润色一个方式的时候,就意味着该方式笼盖父类的方式;而且在编译期间会进行语法查抄!编译器处置完后,"@Override" 就没有任何感化了。
    • b) 若 Annotation 的类型为 CLASS,则意味着:编译器将 Annotation 存储于类对应的 .class 文件中,它是 Annotation 的默认行为。
    • c) 若 Annotation 的类型为 RUNTIME,则意味着:编译器将 Annotation 存储于 class 文件中,而且可由JVM读入。

    这时,只需要记住"每 1 个 Annotation" 都与 "1 个 RetentionPolicy" 联系关系,而且与 "1~n 个 ElementType" 联系关系。学完后面的内容之后,再回头看这些内容,会更容易理解。


    3、java 自带的 Annotation

    理解了上面的 3 个类的感化之后,我们接下来能够讲解 Annotation 实现类的语法定义了。

    1)Annotation 通用定义

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

    申明:

    上面的感化是定义一个 Annotation,它的名字是 MyAnnotation1。定义了 MyAnnotation1 之后,我们能够在代码中通过 "@MyAnnotation1" 来利用它。 其它的,@Documented, @Target, @Retention, @interface 都是来润色 MyAnnotation1 的。下面别离说说它们的寄义:

    (01) @interface

    利用 @interface 定义注释时,意味着它实现了 java.lang.annotation.Annotation 接口,即该注释就是一个Annotation。

    定义 Annotation 时,@interface 是必需的。

    留意:它和我们凡是的 implemented 实现接口的方式分歧。Annotation 接口的实现细节都由编译器完成。通过 @interface 定义注释后,该注释不克不及承继其他的注释或接口。

    (02) @Documented

    类和方式的 Annotation 在缺省环境下是不呈现在 javadoc 中的。若是利用 @Documented 润色该 Annotation,则暗示它能够呈现在 javadoc 中。

    定义 Annotation 时,@Documented 无关紧要;若没有定义,则 Annotation 不会呈现在 javadoc 中。

    (03) @Target(ElementType.TYPE)

    前面我们说过,ElementType 是 Annotation 的类型属性。而 @Target 的感化,就是来指定 Annotation 的类型属性。

    @Target(ElementType.TYPE) 的意义就是指定该 Annotation 的类型是 ElementType.TYPE。这就意味着,MyAnnotation1 是来润色"类、接口(包罗正文类型)或列举声明"的注释。

    定义 Annotation 时,@Target 无关紧要。如有 @Target,则该 Annotation 只能用于它所指定的处所;若没有 @Target,则该 Annotation 能够用于任何处所。

    (04) @Retention(RetentionPolicy.RUNTIME)

    前面我们说过,RetentionPolicy 是 Annotation 的策略属性,而 @Retention 的感化,就是指定 Annotation 的策略属性。

    @Retention(RetentionPolicy.RUNTIME) 的意义就是指定该 Annotation 的策略是 RetentionPolicy.RUNTIME。这就意味着,编译器会将该 Annotation 消息保留在 .class 文件中,而且能被虚拟机读取。

    定义 Annotation 时,@Retention 无关紧要。若没有 @Retention,则默认是 RetentionPolicy.CLASS。

    2)java自带的Annotation

    通过上面的示例,我们能理解:@interface 用来声明 Annotation,@Documented 用来暗示该 Annotation 能否会呈现在 javadoc 中, @Target 用来指定 Annotation 的类型,@Retention 用来指定 Annotation 的策略。

    理解这一点之后,我们就很容易理解 java 中自带的 Annotation 的实现类,即 Annotation 架构图的右半边。如下图:

    java 常用的 Annotation:

    @Deprecated  -- @Deprecated 所标注内容,不再被建议利用。
    @Override    -- @Override 只能标注方式,暗示该方式笼盖父类中的方式。
    @Documented  -- @Documented 所标注内容,能够呈现在javadoc中。
    @Inherited   -- @Inherited只能被用来标注“Annotation类型”,它所标注的Annotation具有承继性。
    @Retention   -- @Retention只能被用来标注“Annotation类型”,并且它被用来指定Annotation的RetentionPolicy属性。
    @Target      -- @Target只能被用来标注“Annotation类型”,并且它被用来指定Annotation的ElementType属性。
    @SuppressWarnings -- @SuppressWarnings 所标注内容发生的警告,编译器会对这些警告连结寂静。

    因为 "@Deprecated 和 @Override" 雷同,"@Documented, @Inherited, @Retention, @Target" 雷同;下面,我们只对 @Deprecated, @Inherited, @SuppressWarnings 这 3 个 Annotation 进行申明。

    2.1) @Deprecated

    @Deprecated 的定义如下:

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

    申明:

    • (01) @interface -- 它的用来润色 Deprecated,意味着 Deprecated 实现了 java.lang.annotation.Annotation 接口;即 Deprecated 就是一个注释。 (02) @Documented -- 它的感化是申明该注释能呈现在 javadoc 中。
    • (03) @Retention(RetentionPolicy.RUNTIME) -- 它的感化是指定 Deprecated 的策略是 RetentionPolicy.RUNTIME。这就意味着,编译器会将Deprecated 的消息保留在 .class 文件中,而且能被虚拟机读取。
    • (04) @Deprecated 所标注内容,不再被建议利用。

    例如,若某个方式被 @Deprecated 标注,则该方式不再被建议利用。若是有开辟人员试图利用或重写被 @Deprecated 标示的方式,编译器会给响应的提醒消息。示例如下:

    DeprecatedTest.java

    import java.util.Date;
    import java.util.Calendar;

    public class DeprecatedTest {
        // @Deprecated 润色 getString1(),暗示 它是建议不被利用的函数
        @Deprecated
        private static void getString1(){
            System.out.println("Deprecated Method");
        }
       
        private static void getString2(){
            System.out.println("Normal Method");
        }
       
        // Date是日期/时间类。java曾经不建议利用该类了
        private static void testDate() {
            Date date = new Date(113, 8, 25);
            System.out.println(date.getYear());
        }
        // Calendar是日期/时间类。java建议利用Calendar代替Date暗示"日期/时间"
        private static void testCalendar() {
            Calendar cal = Calendar.getInstance();
            System.out.println(cal.get(Calendar.YEAR));
        }
       
        public static void main(String[] args) {
            getString1();
            getString2();
            testDate();
            testCalendar();
        }
    }

    申明:

    上面是 eclipse 中的截图,比力类中 "getString1() 和 getString2()" 以和 "testDate() 和 testCalendar()" 。

    (01) getString1() 被 @Deprecated 标注,意味着建议不再利用 getString1(); 所以 getString1() 的定义和挪用时,城市一横线。这一横线是eclipse() 对 @Deprecated 方式的处置。

    getString2() 没有被 @Deprecated 标注,它的显示一般。

    (02) testDate() 挪用了 Date 的相关方式,而 java 曾经建议不再利用 Date 操作日期/时间。因而,在挪用 Date的API 时,会发生警告消息,途中的 warnings。

    testCalendar() 挪用了 Calendar 的 API 来操作日期/时间,java 建议用 Calendar 代替 Date。因而,操作 Calendar 不回发生 warning。

    2.2) @Inherited

    @Inherited 的定义如下:

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

    申明:

    • (01) @interface -- 它的用来润色 Inherited,意味着 Inherited 实现了 java.lang.annotation.Annotation 接口;即 Inherited 就是一个注释。
    • (02) @Documented -- 它的感化是申明该注释能呈现在 javadoc 中。
    • (03) @Retention(RetentionPolicy.RUNTIME) -- 它的感化是指定 Inherited 的策略是 RetentionPolicy.RUNTIME。这就意味着,编译器会将 Inherited 的消息保留在 .class 文件中,而且能被虚拟机读取。
    • (04) @Target(ElementType.ANNOTATION_TYPE) -- 它的感化是指定 Inherited 的类型是 ANNOTATION_TYPE。这就意味着,@Inherited 只能被用来标注 "Annotation 类型"。
    • (05) @Inherited 的寄义是,它所标注的Annotation将具有承继性。
    假设,我们定义了某个 Annotaion,它的名称是 MyAnnotation,而且 MyAnnotation 被标注为 @Inherited。此刻,某个类 Base 利用了

    MyAnnotation,则 Base 具有了"具有了注释 MyAnnotation";此刻,Sub 承继了 Base,因为 MyAnnotation 是 @Inherited的(具有承继性),所以,Sub 也 "具有了注释 MyAnnotation"。

    @Inherited 的利用示例:

    InheritableSon.java

    import java.lang.annotation.Target;
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Inherited;

    /**
     * 自定义的Annotation。
     */

    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @Inherited
    @interface Inheritable
    {
    }

    @Inheritable
    class InheritableFather
    {
        public InheritableFather() {
            // InheritableBase能否具有 Inheritable Annotation
            System.out.println("InheritableFather:"+InheritableFather.class.isAnnotationPresent(Inheritable.class));
        }
    }

    /**
     * InheritableSon 类只是承继于 InheritableFather,
     */

    public class InheritableSon extends InheritableFather
    {
        public InheritableSon() {
            super();    // 挪用父类的机关函数
            // InheritableSon类能否具有 Inheritable Annotation
            System.out.println("InheritableSon:"+InheritableSon.class.isAnnotationPresent(Inheritable.class));
        }
       
        public static void main(String[] args)
        {
            InheritableSon is = new InheritableSon();
        }
    }

    运转成果:

    InheritableFather:true
    InheritableSon:true

    此刻,我们对 InheritableSon.java 进行点窜:正文掉 "Inheritable 的 @Inherited 注释"。

    InheritableSon.java

    import java.lang.annotation.Target;
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Inherited;

    /**
     * 自定义的Annotation。
     */

    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    //@Inherited
    @interface Inheritable
    {
    }

    @Inheritable
    class InheritableFather
    {
        public InheritableFather() {
            // InheritableBase能否具有 Inheritable Annotation
            System.out.println("InheritableFather:"+InheritableFather.class.isAnnotationPresent(Inheritable.class));
        }
    }

    /**
     * InheritableSon 类只是承继于 InheritableFather,
     */

    public class InheritableSon extends InheritableFather
    {
        public InheritableSon() {
            super();    // 挪用父类的机关函数
            // InheritableSon类能否具有 Inheritable Annotation
            System.out.println("InheritableSon:"+InheritableSon.class.isAnnotationPresent(Inheritable.class));
        }
       
        public static void main(String[] args)
        {
            InheritableSon is = new InheritableSon();
        }
    }

    运转成果:

    InheritableFather:true
    InheritableSon:false

    对比上面的两个成果,我们发觉:当注释 Inheritable 被 @Inherited 标注时,它具有承继性。不然,没有承继性。

    2.3) @SuppressWarnings

    @SuppressWarnings 的定义如下:

    @Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
    @Retention(RetentionPolicy.SOURCE)
    public @interface SuppressWarnings {
        String[] value();
    }

    申明:

    (01) @interface -- 它的用来润色 SuppressWarnings,意味着 SuppressWarnings 实现了 java.lang.annotation.Annotation 接口;即 SuppressWarnings 就是一个注释。

    (02) @Retention(RetentionPolicy.SOURCE) -- 它的感化是指定 SuppressWarnings 的策略是 RetentionPolicy.SOURCE。这就意味着,SuppressWarnings 消息仅具有于编译器处置期间,编译器处置完之后 SuppressWarnings 就没有感化了。

    (03) @Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE}) -- 它的感化是指定 SuppressWarnings 的类型同时包罗TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE。

    • TYPE 意味着,它能标注"类、接口(包罗正文类型)或列举声明"。
    • FIELD 意味着,它能标注"字段声明"。
    • METHOD 意味着,它能标注"方式"。
    • PARAMETER 意味着,它能标注"参数"。
    • CONSTRUCTOR 意味着,它能标注"机关方式"。
    • LOCAL_VARIABLE 意味着,它能标注"局部变量"。

    (04) String[] value(); 意味着,SuppressWarnings 能指定参数

    (05) SuppressWarnings 的感化是,让编译器对"它所标注的内容"的某些警告连结寂静。例如,"@SuppressWarnings(value={"deprecation", "unchecked"})" 暗示对"它所标注的内容"中的 "SuppressWarnings 不再建议利用警告"和"未查抄的转换时的警告"连结缄默。示例如下:

    SuppressWarningTest.java

    import java.util.Date;

    public class SuppressWarningTest {

        //@SuppressWarnings(value={"deprecation"})
        public static void doSomething(){
            Date date = new Date(113, 8, 26);
            System.out.println(date);
        }

        public static void main(String[] args) {
            doSomething();
        }
    }

    申明:

    (01) 右边的图中,没有利用 @SuppressWarnings(value={"deprecation"}) , 而 Date 属于 java 不再建议利用的类。因而,挪用 Date 的 API 时,会发生警告。而左边的途中,利用了 @SuppressWarnings(value={"deprecation"})。因而,编译器对"挪用 Date 的 API 发生的警告"连结缄默。

    弥补:SuppressWarnings 常用的环节字的表格

    deprecation  -- 利用了不同意利用的类或方式时的警告
    unchecked    -- 施行了未查抄的转换时的警告,例如当利用调集时没有用泛型 (Generics) 来指定调集保留的类型。
    fallthrough  -- 当 Switch 法式块间接通往下一种环境而没有 Break 时的警告。
    path         -- 在类路径、源文件路径等中有不具有的路径时的警告。
    serial       -- 当在可序列化的类上贫乏 serialVersionUID 定义时的警告。
    finally      -- 任何 finally 子句不克不及一般完成时的警告。
    all          -- 关于以上所无情况的警告。

    4、Annotation 的感化

    Annotation 是一个辅助类,它在 Junit、Struts、Spring 等东西框架中被普遍利用。

    我们在编程中经常会利用到的 Annotation 感化有:

    1)编译查抄

    Annotation 具有"让编译器进行编译查抄的感化"。

    例如,@SuppressWarnings, @Deprecated 和 @Override 都具有编译查抄感化。

    (01) 关于 @SuppressWarnings 和 @Deprecated,曾经在"第3部门"中细致引见过了。这里就不再举例申明了。

    (02) 若某个方式被 @Override 的标注,则意味着该方式会笼盖父类中的同名方式。若是无方法被 @Override 标示,但父类中却没有"被 @Override 标注"的同名方式,则编译器会报错。示例如下:

    OverrideTest.java

    public class OverrideTest {

        /**
         * toString() 在java.lang.Object中定义;
         * 因而,这里用 @Override 标注是对的。
         */

        @Override
        public String toString(){
            return "Override toString";
        }

        /**
         * getString() 没有在OverrideTest的任何父类中定义;
         * 可是,这里却用 @Override 标注,因而会发生编译错误!
         */

        @Override
        public String getString(){
            return "get toString";
        }
       
        public static void main(String[] args) {
        }
    }

    上面是该法式在 eclipse 中的截图。从中,我们能够发觉 "getString()" 函数会报错。这是由于 "getString() 被 @Override 所标注,但在OverrideTest 的任何父类中都没有定义 getString1() 函数"。

    "将 getString() 上面的 @Override正文掉",即可处理该错误。

    2) 在反射中利用 Annotation

    在反射的 Class, Method, Field 等函数中,有很多于 Annotation 相关的接口。

    这也意味着,我们能够在反射中解析并利用 Annotation。

    AnnotationTest.java

    import java.lang.annotation.Annotation;
    import java.lang.annotation.Target;
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Inherited;
    import java.lang.reflect.Method;

    /**
     * Annotation在反射函数中的利用示例
     */

    @Retention(RetentionPolicy.RUNTIME)
    @interface MyAnnotation {
        String[] value() default "unknown";
    }

    /**
     * Person类。它会利用MyAnnotation注释。
     */

    class Person {
       
        /**
         * empty()方式同时被 "@Deprecated" 和 "@MyAnnotation(value={"a","b"})"所标注
         * (01) @Deprecated,意味着empty()方式,不再被建议利用
         * (02) @MyAnnotation, 意味着empty() 方式对应的MyAnnotation的value值是默认值"unknown"
         */

        @MyAnnotation
        @Deprecated
        public void empty(){
            System.out.println("\nempty");
        }
       
        /**
         * sombody() 被 @MyAnnotation(value={"girl","boy"}) 所标注,
         * @MyAnnotation(value={"girl","boy"}), 意味着MyAnnotation的value值是{"girl","boy"}
         */

        @MyAnnotation(value={"girl","boy"})
        public void somebody(String name, int age){
            System.out.println("\nsomebody: "+name+", "+age);
        }
    }

    public class AnnotationTest {

        public static void main(String[] args) throws Exception {
           
            // 新建Person
            Person person = new Person();
            // 获取Person的Class实例
            Class<Person> c = Person.class;
            // 获取 somebody() 方式的Method实例
            Method mSomebody = c.getMethod("somebody", new Class[]{String.class, int.class});
            // 施行该方式
            mSomebody.invoke(person, new Object[]{"lily", 18});
            iteratorAnnotations(mSomebody);
           

            // 获取 somebody() 方式的Method实例
            Method mEmpty = c.getMethod("empty", new Class[]{});
            // 施行该方式
            mEmpty.invoke(person, new Object[]{});        
            iteratorAnnotations(mEmpty);
        }
       
        public static void iteratorAnnotations(Method method) {

            // 判断 somebody() 方式能否包含MyAnnotation注释
            if(method.isAnnotationPresent(MyAnnotation.class)){
                // 获取该方式的MyAnnotation注释实例
                MyAnnotation myAnnotation = method.getAnnotation(MyAnnotation.class);
                // 获取 myAnnotation的值,并打印出来
                String[] values = myAnnotation.value();
                for (String str:values)
                    System.out.printf(str+", ");
                System.out.println();
            }
           
            // 获取方式上的所有注释,并打印出来
            Annotation[] annotations = method.getAnnotations();
            for(Annotation annotation : annotations){
                System.out.println(annotation);
            }
        }
    }

    运转成果:

    somebody: lily, 18
    girl, boy, 
    @com.skywang.annotation.MyAnnotation(value=[girl, boy])
    
    empty
    unknown, 
    @com.skywang.annotation.MyAnnotation(value=[unknown])
    @java.lang.Deprecated()

    3) 按照 Annotation 生成帮忙文档

    通过给 Annotation 注释加上 @Documented 标签,能使该 Annotation 标签呈现在 javadoc 中。

    4) 可以或许帮手查看查看代码

    通过 @Override, @Deprecated 等,我们能很便利的领会法式的大致布局。

    别的,我们也能够通过自定义 Annotation 来实现一些功能。

    本文由亚博编辑整理"/>

    Java 注释(Annotation)又称 Java 标注,是 JDK5.0 引入的一种正文机制。

    Java 言语中的类、方式、变量、参数和包等都能够被标注。和 Javadoc 分歧,Java 标注能够通过反射获取标注内容。在编译器生成类文件时,标注能够被嵌入到字节码中。Java 虚拟机能够保留标注内容,在运转时能够获取到标注内容 。 当然它也支撑自定义 Java 标注。

    网上良多关于 Java Annotation 的文章,看得人目炫狼籍。Java Annotation 本来很简单的,成果说的人没说清晰;弄的看的人愈加含混。

    我按照本身的思绪,对 Annotation 进行了拾掇。理解 Annotation 的环节,是理解 Annotation 的语法和用法,对这些内容,我都进行了细致申明;理解 Annotation 的语法和用法之后,再看 Annotation 的框架图,可能有更深刻体味。废话就说这么多,下面起头对 Annotation 进行申明。若您发觉文章中具有错误或不足的处所,但愿您能指出!

    内置的注释

    Java 定义了一套注释,共有 7 个,3 个在 java.lang 中,剩下 4 个在 java.lang.annotation 中。

    感化在代码的注释是

    • 亚博手机app@Override - 查抄该方式能否是重载方式。若是发觉其父类,或者是援用的接口中并没有该方式时,会报编译错误。
    • @Deprecated - 标识表记标帜过时方式。若是利用该方式,会报编译警告。
    • @SuppressWarnings - 指示编译器去忽略注释中声明的警告。

    感化在其他注释的注释(或者说 元注释)是:

    • @Retention - 标识这个注释怎样保留,是只在代码中,仍是编入class文件中,或者是在运转时能够通过反射拜候。
    • @Documented - 标识表记标帜这些注释能否包含在用户文档中。
    • @Target - 标识表记标帜这个注释该当是哪种 Java 成员。
    • @Inherited - 标识表记标帜这个注释是承继于哪个注释类(默认 注释并没有承继于任何子类)

    从 Java 7 起头,额外添加了 3 个注释:

    • @SafeVarargs - Java 7 起头支撑,忽略任何利用参数为泛型变量的方式或机关函数挪用发生的警告。
    • @FunctionalInterface - Java 8 起头支撑,标识一个匿名函数或函数式接口。
    • @Repeatable - Java 8 起头支撑,标识某注释能够在统一个声明上利用多次。

    1、Annotation 架构

    从中,我们能够看出:

    (01) 1 个 Annotation 和 1 个 RetentionPolicy 联系关系。

    能够理解为:每1个Annotation对象,城市有独一的RetentionPolicy属性。

    (02) 1 个 Annotation 和 1~n 个 ElementType 联系关系。

    能够理解为:对于每 1 个 Annotation 对象,能够有若干个 ElementType 属性。

    (03) Annotation 有很多实现类,包罗:Deprecated, Documented, Inherited, Override 等等。

    Annotation 的每一个实现类,都 "和 1 个 RetentionPolicy 联系关系" 而且 " 和 1~n 个 ElementType 联系关系"。

    下面,我先引见框架图的左半边(如下图),即 Annotation, RetentionPolicy, ElementType;然后在就 Annotation 的实现类进行举例申明。


    2、Annotation 构成部门

    java Annotation 的构成中,有 3 个很是主要的主干类。它们别离是:

    Annotation.java

    package java.lang.annotation;
    public interface Annotation {

        boolean equals(Object obj);

        int hashCode();

        String toString();

        Class<? extends Annotation> annotationType();
    }

    ElementType.java

    package java.lang.annotation;

    public enum ElementType {
        TYPE,               /* 类、接口(包罗正文类型)或列举声明  */

        FIELD,              /* 字段声明(包罗列举常量)  */

        METHOD,             /* 方式声明  */

        PARAMETER,          /* 参数声明  */

        CONSTRUCTOR,        /* 机关方式声明  */

        LOCAL_VARIABLE,     /* 局部变量声明  */

        ANNOTATION_TYPE,    /* 正文类型声明  */

        PACKAGE             /* 包声明  */
    }

    RetentionPolicy.java

    package java.lang.annotation;
    public enum RetentionPolicy {
        SOURCE,            /* Annotation消息仅具有于编译器处置期间,编译器处置完之后就没有该Annotation消息了  */

        CLASS,             /* 编译器将Annotation存储于类对应的.class文件中。默认行为  */

        RUNTIME            /* 编译器将Annotation存储于class文件中,而且可由JVM读入 */
    }

    申明:

    (01) Annotation 就是个接口。

    "每 1 个 Annotation" 都与 "1 个 RetentionPolicy" 联系关系,而且与 "1~n 个 ElementType" 联系关系。能够通俗的理解为:每 1 个 Annotation 对象,城市有独一的 RetentionPolicy 属性;至于 ElementType 属性,则有 1~n 个。

    (02) ElementType 是 Enum 列举类型,它用来指定 Annotation 的类型。

    "每 1 个 Annotation" 都与 "1~n 个 ElementType" 联系关系。当 Annotation 与某个 ElementType 联系关系时,就意味着:Annotation有了某种用处。例如,若一个 Annotation 对象是 METHOD 类型,则该 Annotation 只能用来润色方式。

    (03) RetentionPolicy 是 Enum 列举类型,它用来指定 Annotation 的策略。通俗点说,就是分歧 RetentionPolicy 类型的 Annotation 的感化域分歧。

    "每 1 个 Annotation" 都与 "1 个 RetentionPolicy" 联系关系。

    • a) 若 Annotation 的类型为 SOURCE,则意味着:Annotation 仅具有于编译器处置期间,编译器处置完之后,该 Annotation 就没用了。 例如," @Override" 标记就是一个 Annotation。当它润色一个方式的时候,就意味着该方式笼盖父类的方式;而且在编译期间会进行语法查抄!编译器处置完后,"@Override" 就没有任何感化了。
    • b) 若 Annotation 的类型为 CLASS,则意味着:编译器将 Annotation 存储于类对应的 .class 文件中,它是 Annotation 的默认行为。
    • c) 若 Annotation 的类型为 RUNTIME,则意味着:编译器将 Annotation 存储于 class 文件中,而且可由JVM读入。

    这时,只需要记住"每 1 个 Annotation" 都与 "1 个 RetentionPolicy" 联系关系,而且与 "1~n 个 ElementType" 联系关系。学完后面的内容之后,再回头看这些内容,会更容易理解。


    3、java 自带的 Annotation

    理解了上面的 3 个类的感化之后,我们接下来能够讲解 Annotation 实现类的语法定义了。

    1)Annotation 通用定义

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

    申明:

    上面的感化是定义一个 Annotation,它的名字是 MyAnnotation1。定义了 MyAnnotation1 之后,我们能够在代码中通过 "@MyAnnotation1" 来利用它。 其它的,@Documented, @Target, @Retention, @interface 都是来润色 MyAnnotation1 的。下面别离说说它们的寄义:

    (01) @interface

    利用 @interface 定义注释时,意味着它实现了 java.lang.annotation.Annotation 接口,即该注释就是一个Annotation。

    定义 Annotation 时,@interface 是必需的。

    留意:它和我们凡是的 implemented 实现接口的方式分歧。Annotation 接口的实现细节都由编译器完成。通过 @interface 定义注释后,该注释不克不及承继其他的注释或接口。

    (02) @Documented

    类和方式的 Annotation 在缺省环境下是不呈现在 javadoc 中的。若是利用 @Documented 润色该 Annotation,则暗示它能够呈现在 javadoc 中。

    定义 Annotation 时,@Documented 无关紧要;若没有定义,则 Annotation 不会呈现在 javadoc 中。

    (03) @Target(ElementType.TYPE)

    前面我们说过,ElementType 是 Annotation 的类型属性。而 @Target 的感化,就是来指定 Annotation 的类型属性。

    @Target(ElementType.TYPE) 的意义就是指定该 Annotation 的类型是 ElementType.TYPE。这就意味着,MyAnnotation1 是来润色"类、接口(包罗正文类型)或列举声明"的注释。

    定义 Annotation 时,@Target 无关紧要。如有 @Target,则该 Annotation 只能用于它所指定的处所;若没有 @Target,则该 Annotation 能够用于任何处所。

    (04) @Retention(RetentionPolicy.RUNTIME)

    前面我们说过,RetentionPolicy 是 Annotation 的策略属性,而 @Retention 的感化,就是指定 Annotation 的策略属性。

    @Retention(RetentionPolicy.RUNTIME) 的意义就是指定该 Annotation 的策略是 RetentionPolicy.RUNTIME。这就意味着,编译器会将该 Annotation 消息保留在 .class 文件中,而且能被虚拟机读取。

    定义 Annotation 时,@Retention 无关紧要。若没有 @Retention,则默认是 RetentionPolicy.CLASS。

    2)java自带的Annotation

    通过上面的示例,我们能理解:@interface 用来声明 Annotation,@Documented 用来暗示该 Annotation 能否会呈现在 javadoc 中, @Target 用来指定 Annotation 的类型,@Retention 用来指定 Annotation 的策略。

    理解这一点之后,我们就很容易理解 java 中自带的 Annotation 的实现类,即 Annotation 架构图的右半边。如下图:

    java 常用的 Annotation:

    @Deprecated  -- @Deprecated 所标注内容,不再被建议利用。
    @Override    -- @Override 只能标注方式,暗示该方式笼盖父类中的方式。
    @Documented  -- @Documented 所标注内容,能够呈现在javadoc中。
    @Inherited   -- @Inherited只能被用来标注“Annotation类型”,它所标注的Annotation具有承继性。
    @Retention   -- @Retention只能被用来标注“Annotation类型”,并且它被用来指定Annotation的RetentionPolicy属性。
    @Target      -- @Target只能被用来标注“Annotation类型”,并且它被用来指定Annotation的ElementType属性。
    @SuppressWarnings -- @SuppressWarnings 所标注内容发生的警告,编译器会对这些警告连结寂静。

    因为 "@Deprecated 和 @Override" 雷同,"@Documented, @Inherited, @Retention, @Target" 雷同;下面,我们只对 @Deprecated, @Inherited, @SuppressWarnings 这 3 个 Annotation 进行申明。

    2.1) @Deprecated

    @Deprecated 的定义如下:

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

    申明:

    • (01) @interface -- 它的用来润色 Deprecated,意味着 Deprecated 实现了 java.lang.annotation.Annotation 接口;即 Deprecated 就是一个注释。 (02) @Documented -- 它的感化是申明该注释能呈现在 javadoc 中。
    • (03) @Retention(RetentionPolicy.RUNTIME) -- 它的感化是指定 Deprecated 的策略是 RetentionPolicy.RUNTIME。这就意味着,编译器会将Deprecated 的消息保留在 .class 文件中,而且能被虚拟机读取。
    • (04) @Deprecated 所标注内容,不再被建议利用。

    例如,若某个方式被 @Deprecated 标注,则该方式不再被建议利用。若是有开辟人员试图利用或重写被 @Deprecated 标示的方式,编译器会给响应的提醒消息。示例如下:

    DeprecatedTest.java

    import java.util.Date;
    import java.util.Calendar;

    public class DeprecatedTest {
        // @Deprecated 润色 getString1(),暗示 它是建议不被利用的函数
        @Deprecated
        private static void getString1(){
            System.out.println("Deprecated Method");
        }
       
        private static void getString2(){
            System.out.println("Normal Method");
        }
       
        // Date是日期/时间类。java曾经不建议利用该类了
        private static void testDate() {
            Date date = new Date(113, 8, 25);
            System.out.println(date.getYear());
        }
        // Calendar是日期/时间类。java建议利用Calendar代替Date暗示"日期/时间"
        private static void testCalendar() {
            Calendar cal = Calendar.getInstance();
            System.out.println(cal.get(Calendar.YEAR));
        }
       
        public static void main(String[] args) {
            getString1();
            getString2();
            testDate();
            testCalendar();
        }
    }

    申明:

    上面是 eclipse 中的截图,比力类中 "getString1() 和 getString2()" 以和 "testDate() 和 testCalendar()" 。

    (01) getString1() 被 @Deprecated 标注,意味着建议不再利用 getString1(); 所以 getString1() 的定义和挪用时,城市一横线。这一横线是eclipse() 对 @Deprecated 方式的处置。

    getString2() 没有被 @Deprecated 标注,它的显示一般。

    (02) testDate() 挪用了 Date 的相关方式,而 java 曾经建议不再利用 Date 操作日期/时间。因而,在挪用 Date的API 时,会发生警告消息,途中的 warnings。

    testCalendar() 挪用了 Calendar 的 API 来操作日期/时间,java 建议用 Calendar 代替 Date。因而,操作 Calendar 不回发生 warning。

    2.2) @Inherited

    @Inherited 的定义如下:

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

    申明:

    • (01) @interface -- 它的用来润色 Inherited,意味着 Inherited 实现了 java.lang.annotation.Annotation 接口;即 Inherited 就是一个注释。
    • (02) @Documented -- 它的感化是申明该注释能呈现在 javadoc 中。
    • (03) @Retention(RetentionPolicy.RUNTIME) -- 它的感化是指定 Inherited 的策略是 RetentionPolicy.RUNTIME。这就意味着,编译器会将 Inherited 的消息保留在 .class 文件中,而且能被虚拟机读取。
    • (04) @Target(ElementType.ANNOTATION_TYPE) -- 它的感化是指定 Inherited 的类型是 ANNOTATION_TYPE。这就意味着,@Inherited 只能被用来标注 "Annotation 类型"。
    • (05) @Inherited 的寄义是,它所标注的Annotation将具有承继性。
    假设,我们定义了某个 Annotaion,它的名称是 MyAnnotation,而且 MyAnnotation 被标注为 @Inherited。此刻,某个类 Base 利用了

    MyAnnotation,则 Base 具有了"具有了注释 MyAnnotation";此刻,Sub 承继了 Base,因为 MyAnnotation 是 @Inherited的(具有承继性),所以,Sub 也 "具有了注释 MyAnnotation"。

    @Inherited 的利用示例:

    InheritableSon.java

    import java.lang.annotation.Target;
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Inherited;

    /**
     * 自定义的Annotation。
     */

    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @Inherited
    @interface Inheritable
    {
    }

    @Inheritable
    class InheritableFather
    {
        public InheritableFather() {
            // InheritableBase能否具有 Inheritable Annotation
            System.out.println("InheritableFather:"+InheritableFather.class.isAnnotationPresent(Inheritable.class));
        }
    }

    /**
     * InheritableSon 类只是承继于 InheritableFather,
     */

    public class InheritableSon extends InheritableFather
    {
        public InheritableSon() {
            super();    // 挪用父类的机关函数
            // InheritableSon类能否具有 Inheritable Annotation
            System.out.println("InheritableSon:"+InheritableSon.class.isAnnotationPresent(Inheritable.class));
        }
       
        public static void main(String[] args)
        {
            InheritableSon is = new InheritableSon();
        }
    }

    运转成果:

    InheritableFather:true
    InheritableSon:true

    此刻,我们对 InheritableSon.java 进行点窜:正文掉 "Inheritable 的 @Inherited 注释"。

    InheritableSon.java

    import java.lang.annotation.Target;
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Inherited;

    /**
     * 自定义的Annotation。
     */

    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    //@Inherited
    @interface Inheritable
    {
    }

    @Inheritable
    class InheritableFather
    {
        public InheritableFather() {
            // InheritableBase能否具有 Inheritable Annotation
            System.out.println("InheritableFather:"+InheritableFather.class.isAnnotationPresent(Inheritable.class));
        }
    }

    /**
     * InheritableSon 类只是承继于 InheritableFather,
     */

    public class InheritableSon extends InheritableFather
    {
        public InheritableSon() {
            super();    // 挪用父类的机关函数
            // InheritableSon类能否具有 Inheritable Annotation
            System.out.println("InheritableSon:"+InheritableSon.class.isAnnotationPresent(Inheritable.class));
        }
       
        public static void main(String[] args)
        {
            InheritableSon is = new InheritableSon();
        }
    }

    运转成果:

    InheritableFather:true
    InheritableSon:false

    对比上面的两个成果,我们发觉:当注释 Inheritable 被 @Inherited 标注时,它具有承继性。不然,没有承继性。

    2.3) @SuppressWarnings

    @SuppressWarnings 的定义如下:

    @Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
    @Retention(RetentionPolicy.SOURCE)
    public @interface SuppressWarnings {
        String[] value();
    }

    申明:

    (01) @interface -- 它的用来润色 SuppressWarnings,意味着 SuppressWarnings 实现了 java.lang.annotation.Annotation 接口;即 SuppressWarnings 就是一个注释。

    (02) @Retention(RetentionPolicy.SOURCE) -- 它的感化是指定 SuppressWarnings 的策略是 RetentionPolicy.SOURCE。这就意味着,SuppressWarnings 消息仅具有于编译器处置期间,编译器处置完之后 SuppressWarnings 就没有感化了。

    (03) @Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE}) -- 它的感化是指定 SuppressWarnings 的类型同时包罗TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE。

    • TYPE 意味着,它能标注"类、接口(包罗正文类型)或列举声明"。
    • FIELD 意味着,它能标注"字段声明"。
    • METHOD 意味着,它能标注"方式"。
    • PARAMETER 意味着,它能标注"参数"。
    • CONSTRUCTOR 意味着,它能标注"机关方式"。
    • LOCAL_VARIABLE 意味着,它能标注"局部变量"。

    (04) String[] value(); 意味着,SuppressWarnings 能指定参数

    (05) SuppressWarnings 的感化是,让编译器对"它所标注的内容"的某些警告连结寂静。例如,"@SuppressWarnings(value={"deprecation", "unchecked"})" 暗示对"它所标注的内容"中的 "SuppressWarnings 不再建议利用警告"和"未查抄的转换时的警告"连结缄默。示例如下:

    SuppressWarningTest.java

    import java.util.Date;

    public class SuppressWarningTest {

        //@SuppressWarnings(value={"deprecation"})
        public static void doSomething(){
            Date date = new Date(113, 8, 26);
            System.out.println(date);
        }

        public static void main(String[] args) {
            doSomething();
        }
    }

    申明:

    (01) 右边的图中,没有利用 @SuppressWarnings(value={"deprecation"}) , 而 Date 属于 java 不再建议利用的类。因而,挪用 Date 的 API 时,会发生警告。而左边的途中,利用了 @SuppressWarnings(value={"deprecation"})。因而,编译器对"挪用 Date 的 API 发生的警告"连结缄默。

    弥补:SuppressWarnings 常用的环节字的表格

    deprecation  -- 利用了不同意利用的类或方式时的警告
    unchecked    -- 施行了未查抄的转换时的警告,例如当利用调集时没有用泛型 (Generics) 来指定调集保留的类型。
    fallthrough  -- 当 Switch 法式块间接通往下一种环境而没有 Break 时的警告。
    path         -- 在类路径、源文件路径等中有不具有的路径时的警告。
    serial       -- 当在可序列化的类上贫乏 serialVersionUID 定义时的警告。
    finally      -- 任何 finally 子句不克不及一般完成时的警告。
    all          -- 关于以上所无情况的警告。

    4、Annotation 的感化

    Annotation 是一个辅助类,它在 Junit、Struts、Spring 等东西框架中被普遍利用。

    我们在编程中经常会利用到的 Annotation 感化有:

    1)编译查抄

    Annotation 具有"让编译器进行编译查抄的感化"。

    例如,@SuppressWarnings, @Deprecated 和 @Override 都具有编译查抄感化。

    (01) 关于 @SuppressWarnings 和 @Deprecated,曾经在"第3部门"中细致引见过了。这里就不再举例申明了。

    (02) 若某个方式被 @Override 的标注,则意味着该方式会笼盖父类中的同名方式。若是无方法被 @Override 标示,但父类中却没有"被 @Override 标注"的同名方式,则编译器会报错。示例如下:

    OverrideTest.java

    public class OverrideTest {

        /**
         * toString() 在java.lang.Object中定义;
         * 因而,这里用 @Override 标注是对的。
         */

        @Override
        public String toString(){
            return "Override toString";
        }

        /**
         * getString() 没有在OverrideTest的任何父类中定义;
         * 可是,这里却用 @Override 标注,因而会发生编译错误!
         */

        @Override
        public String getString(){
            return "get toString";
        }
       
        public static void main(String[] args) {
        }
    }

    上面是该法式在 eclipse 中的截图。从中,我们能够发觉 "getString()" 函数会报错。这是由于 "getString() 被 @Override 所标注,但在OverrideTest 的任何父类中都没有定义 getString1() 函数"。

    "将 getString() 上面的 @Override正文掉",即可处理该错误。

    2) 在反射中利用 Annotation

    在反射的 Class, Method, Field 等函数中,有很多于 Annotation 相关的接口。

    这也意味着,我们能够在反射中解析并利用 Annotation。

    AnnotationTest.java

    import java.lang.annotation.Annotation;
    import java.lang.annotation.Target;
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Inherited;
    import java.lang.reflect.Method;

    /**
     * Annotation在反射函数中的利用示例
     */

    @Retention(RetentionPolicy.RUNTIME)
    @interface MyAnnotation {
        String[] value() default "unknown";
    }

    /**
     * Person类。它会利用MyAnnotation注释。
     */

    class Person {
       
        /**
         * empty()方式同时被 "@Deprecated" 和 "@MyAnnotation(value={"a","b"})"所标注
         * (01) @Deprecated,意味着empty()方式,不再被建议利用
         * (02) @MyAnnotation, 意味着empty() 方式对应的MyAnnotation的value值是默认值"unknown"
         */

        @MyAnnotation
        @Deprecated
        public void empty(){
            System.out.println("\nempty");
        }
       
        /**
         * sombody() 被 @MyAnnotation(value={"girl","boy"}) 所标注,
         * @MyAnnotation(value={"girl","boy"}), 意味着MyAnnotation的value值是{"girl","boy"}
         */

        @MyAnnotation(value={"girl","boy"})
        public void somebody(String name, int age){
            System.out.println("\nsomebody: "+name+", "+age);
        }
    }

    public class AnnotationTest {

        public static void main(String[] args) throws Exception {
           
            // 新建Person
            Person person = new Person();
            // 获取Person的Class实例
            Class<Person> c = Person.class;
            // 获取 somebody() 方式的Method实例
            Method mSomebody = c.getMethod("somebody", new Class[]{String.class, int.class});
            // 施行该方式
            mSomebody.invoke(person, new Object[]{"lily", 18});
            iteratorAnnotations(mSomebody);
           

            // 获取 somebody() 方式的Method实例
            Method mEmpty = c.getMethod("empty", new Class[]{});
            // 施行该方式
            mEmpty.invoke(person, new Object[]{});        
            iteratorAnnotations(mEmpty);
        }
       
        public static void iteratorAnnotations(Method method) {

            // 判断 somebody() 方式能否包含MyAnnotation注释
            if(method.isAnnotationPresent(MyAnnotation.class)){
                // 获取该方式的MyAnnotation注释实例
                MyAnnotation myAnnotation = method.getAnnotation(MyAnnotation.class);
                // 获取 myAnnotation的值,并打印出来
                String[] values = myAnnotation.value();
                for (String str:values)
                    System.out.printf(str+", ");
                System.out.println();
            }
           
            // 获取方式上的所有注释,并打印出来
            Annotation[] annotations = method.getAnnotations();
            for(Annotation annotation : annotations){
                System.out.println(annotation);
            }
        }
    }

    运转成果:

    somebody: lily, 18
    girl, boy, 
    @com.skywang.annotation.MyAnnotation(value=[girl, boy])
    
    empty
    unknown, 
    @com.skywang.annotation.MyAnnotation(value=[unknown])
    @java.lang.Deprecated()

    3) 按照 Annotation 生成帮忙文档

    通过给 Annotation 注释加上 @Documented 标签,能使该 Annotation 标签呈现在 javadoc 中。

    4) 可以或许帮手查看查看代码

    通过 @Override, @Deprecated 等,我们能很便利的领会法式的大致布局。

    别的,我们也能够通过自定义 Annotation 来实现一些功能。

    本文由亚博编辑整理亚博手机app