Java 注解介绍

qvuy6712 7年前
   <h2>前言</h2>    <p>Java注解介绍</p>    <h2>1. 注解中最重要的三个类</h2>    <p>Annotation 、 ElementType 、 RetentionPolicy 这三个类是注解中最重要的类, <strong>没有这三个类就没有注解</strong> ,其中 Annotation 是接口,其余两个是枚举。</p>    <p>所有的注解都基于这三个类,所谓的 <em>元注解</em> 也是用这三个类生成的,只不过可修饰的元素(ElementType)为ANNOTATION_TYPE罢了,你也可以写个元注解。</p>    <p>1. Annotation</p>    <pre>  <code class="language-java">package java.lang.annotation; //java.lang.annotation包下  public interface Annotation {      boolean equals(Object var1);        int hashCode();        String toString();        Class<? extends Annotation> annotationType();  }</code></pre>    <p>2. ElementType</p>    <pre>  <code class="language-java">package java.lang.annotation; //java.lang.annotation包下  public enum ElementType {      TYPE,  // 类、接口(包括注释类型)或枚举声明      FIELD,  // 字段声明(包括枚举常量)      METHOD,  //方法声明      PARAMETER,  //参数声明      CONSTRUCTOR,  //构造方法声明      LOCAL_VARIABLE,  //局部变量声明      ANNOTATION_TYPE,  //注解类型声明      PACKAGE,  //包声明      TYPE_PARAMETER,  //类型参数声明(1.8新加入),表示这个注解可以用来标注类型参数      TYPE_USE; //类型使用声明(1.8新加入),用于标注各种类型,只要是类型名称,都可以进行注解        private ElementType() {      }  }</code></pre>    <p>3. RetentionPolicy</p>    <pre>  <code class="language-java">package java.lang.annotation;//java.lang.annotation包下  public enum RetentionPolicy {      SOURCE,  //注解将被编译器丢弃;Annotation信息仅存在于编译器处理期间,编译器处理完之后就没有该Annotation信息了      CLASS,  //注解在class文件中可用,但会被VM丢弃      RUNTIME;  //VM将在运行期也保留注解信息,因此可以通过反射机制读取注解的信息        private RetentionPolicy() {      }  }</code></pre>    <h2>2. 四种元注解</h2>    <p>Java提供了四种元注解(meta-annotation),元注解就是专职负责注解其他的注解,所以这四种注解的Target值都是ElementType.ANNOTATION_TYPE</p>    <p>1. @Target</p>    <p>表示该注解可以用在什么地方,由ElementType枚举定义</p>    <pre>  <code class="language-java">@Documented  @Retention(RetentionPolicy.RUNTIME) //被VM识别  @Target({ElementType.ANNOTATION_TYPE}) //修饰注解类型  public @interface Target {      ElementType[] value(); //当使用此注解时,无默认注解,必须要传入ElementType  }</code></pre>    <p>2. @Retention</p>    <p>表示需要在什么级别保存该注解信息,由RetentionPolicy枚举定义</p>    <pre>  <code class="language-java">@Documented  @Retention(RetentionPolicy.RUNTIME)  @Target({ElementType.ANNOTATION_TYPE})  public @interface Retention {      RetentionPolicy value(); // 必须要传入  }</code></pre>    <p>3. @Documented</p>    <p>表示注解会被包含在javaapi文档中</p>    <pre>  <code class="language-java">@Documented  @Retention(RetentionPolicy.RUNTIME)  @Target({ElementType.ANNOTATION_TYPE})  public @interface Documented {  }</code></pre>    <p>4. @Inherited</p>    <p>允许子类继承父类的注解,即它所标注的Annotation将具有继承性</p>    <pre>  <code class="language-java">@Documented  @Retention(RetentionPolicy.RUNTIME)  @Target({ElementType.ANNOTATION_TYPE})  public @interface Inherited {  }</code></pre>    <h2>3. 注解的基本语法</h2>    <pre>  <code class="language-java">//@Target(ElementType.Method)      //@Retention(RetentionPolicy.RUNTIME)    public @interface MyAnnotation {       int id(); // default 1; 不添加default值使用该注解时必须要传入传入       String value() default ""; //如果只有value()这一个属性需要赋值的话,可以省略键值对传值       // Integer id() default 1; //抛出异常,Invalid type    }</code></pre>    <ol>     <li> <p>@interface表示该类是一个注解,并实现了 Annotation接口 。</p> </li>     <li> <p>@Target表示该注解可以修饰的类型;如果不填,则此注解可以使用任何元素之上;</p> </li>     <li> <p>@Retention用来定义注解在哪一个级别可用,是源码中可见、编译器可见还是VM可见;如果不填,默认级别是CLASS。</p> </li>     <li> <p>注解元素可用的类型</p> <p>所有基本类型(int,float,boolean,byte,double,char,long,short)、 String、Class、enum、Annotation和以上类型的数组;其它的值都会抛出 Error: 注释值不是允许的类型 。</p> </li>     <li> <p>注解的快捷方式</p> <p>当注解内元素方法名为value()时, <strong>并且该元素是唯一一个需要赋值的值</strong> (另外的值有默认值),可以不用使用键值对来传值,直接使用 @MyAnnotation("2") 传值;如果有两个,则要使用 @MyAnnotation(id=1,value = "2") 来传值。</p> </li>    </ol>    <h2>4. Java常用的注解</h2>    <p>1. @Deprecated</p>    <p>所标注内容,不再被建议使用。</p>    <pre>  <code class="language-java">@Documented  @Retention(RetentionPolicy.RUNTIME)  @Target({ElementType.CONSTRUCTOR, ElementType.FIELD, ElementType.LOCAL_VARIABLE, ElementType.METHOD, ElementType.PACKAGE, ElementType.PARAMETER, ElementType.TYPE})  public @interface Deprecated {  }</code></pre>    <p>2. @Override</p>    <p>只能标注方法,表示该方法覆盖父类中的方法。</p>    <pre>  <code class="language-java">@Target({ElementType.METHOD})  @Retention(RetentionPolicy.SOURCE)  public @interface Override {  }</code></pre>    <p>3. @SuppressWarnings</p>    <p>所标注内容产生的警告,编译器会对这些警告保持静默。</p>    <pre>  <code class="language-java">@Target({ElementType.TYPE, ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.CONSTRUCTOR, ElementType.LOCAL_VARIABLE})  @Retention(RetentionPolicy.SOURCE)  public @interface SuppressWarnings {      String[] value();  }  /*  value可取的值:  deprecation  -- 使用了不赞成使用的类或方法时的警告  unchecked    -- 执行了未检查的转换时的警告,例如当使用集合时没有用泛型 (Generics) 来指定集合保存的类型。  fallthrough  -- 当 Switch 程序块直接通往下一种情况而没有 Break 时的警告。  path         -- 在类路径、源文件路径等中有不存在的路径时的警告。  serial       -- 当在可序列化的类上缺少 serialVersionUID 定义时的警告。  finally      -- 任何 finally 子句不能正常完成时的警告。  all          -- 关于以上所有情况的警告。  */</code></pre>    <h2>5. 处理注解</h2>    <p>Java处理注解有两种方式:</p>    <ol>     <li> <p>使用apt来在编译时期生成相应的代码,通过注解处理器(AnnotationProcessor)来处理</p> </li>     <li> <p>在运行时通过反射获取注解信息来处理</p> </li>    </ol>    <p>这块之后专门来学习,这篇文章不赘述了。</p>    <h2>6. 注解的作用</h2>    <ol>     <li> <p>生成文档。这是最常见的,也是java 最早提供的注解。常用的有@see @param @return 等</p> </li>     <li> <p>代码分析,跟踪代码依赖性。如JUnit框架的注解使用。</p> </li>     <li> <p>在编译时进行格式检查。如@override 放在方法前,如果你这个方法并不是覆盖了超类方法,则编译时就能检查出。</p> </li>    </ol>    <h2>结语</h2>    <p>本篇文章介绍注解的基本概念和作用,对注解的基本有个清晰的了解,之后再单独写对注解的处理。</p>    <h2>参考:</h2>    <p><a href="/misc/goto?guid=4959742018940013793" rel="nofollow,noindex">Java Annotation认知(包括框架图、详细介绍、示例说明)</a></p>    <p><a href="/misc/goto?guid=4959663055170388257" rel="nofollow,noindex">Java注解全面解析</a></p>    <p><a href="/misc/goto?guid=4959742019055594587" rel="nofollow,noindex">Java深度历险(六)——Java注解</a></p>    <p> </p>    <p>来自:https://juejin.im/post/58cabc0e44d9040069f39fd7</p>    <p> </p>