【JDK8新特性】8.重复注解与类型注解

重复注解与类型注解

基于尚硅谷java8教程

1. 重复注解

重复注解就是运行在同一个地方(类、方法、属性)重复使用同一个注解。可以配合反射进行使用
注意:

JEP=JDK Enhancement-Proposal (JDK 增强建议 ),每个JEP即一个新特性。在java 8里面,注解一共有2个改进,一个是重复注解(JEP 120),另一个就是类型注解(JEP104)

使用重复注解可以提供系统代码可读性。

  • 定义重复注解
  /* MyAnnotation.java */
  package com.seven.jdk8.anno;

  import java.lang.annotation.*;

  import static java.lang.annotation.ElementType.*;
  
  /**
   * 定义注解,,如果需要使用重复注解,需要添加@Repeatable(MyAnnotations.class),其中MyAnnotations.class是容器类,用来存放MyAnnotation注解
   */
  @Repeatable(MyAnnotations.class)
  @Retention(RetentionPolicy.RUNTIME)
  @Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE})
  public @interface MyAnnotation {
      String value() default  "my.annotation";
  }
  
  /* MyAnnotations.java */

  package com.seven.jdk8.anno;

  import java.lang.annotation.Retention;
  import java.lang.annotation.RetentionPolicy;
  import java.lang.annotation.Target;
  
  import static java.lang.annotation.ElementType.*;
  
  /**
   * .本类是MyAnnotation的容器类,用来存放MyAnnotation注解,所以参数为数组类,并且参数名称与MyAnnotation中的参数名称一致
   */
  @Retention(RetentionPolicy.RUNTIME)
  @Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE})
  public @interface MyAnnotations {
      MyAnnotation[] value();
  }

  • 使用重复注解

  
  /**
   * 重复注解测试,可以使用反射的方式使用重复注解
   */
  public class RepeateAnnotationTest {
  
      @Test
      public void test() throws NoSuchMethodException {
          Class<RepeateAnnotationTest> clz = RepeateAnnotationTest.class;
          Method method = clz.getMethod("show");
          
          MyAnnotation[] mas =  method.getAnnotationsByType(MyAnnotation.class);
          for(MyAnnotation ma:mas){
              System.out.println(ma.value());
          }
      }
      @MyAnnotation("hello")
      @MyAnnotation("world")
      public void show(){
  
      }
  }
  

2. 类型注解

  • jdk8中新增的注解类型
    新增ElementType.TYPE_USE 和ElementType.TYPE_PARAMETER(在Target上)。
    ElementType.TYPE_PARAMETER 表示该注解能写在类型变量的声明语句中。
    ElementType.TYPE_USE 表示该注解能写在使用类型的任何语句中(eg:声明语句、泛型和强制转换语句中的类型)。

    @Target({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE})  
    @interface MyAnnotation {}
    
  • 类型注解的作用
    类型注解被用来支持在Java的程序中做强类型检查。配合第三方插件工具Checker Framework,可以在编译的时候检测出runtime error(eg:UnsupportedOperationException; NumberFormatException;NullPointerException异常等都是runtime error),以提高代码质量。这就是类型注解的作用。

  • check framework

    check framework是第三方工具,配合Java的类型注解效果就是1+1>2。它可以嵌入到javac编译器里面,可以配合ant和maven使用,也可以作为eclipse插件。地址是http://types.cs.washington.edu/checker-framework/。
    check framework可以找到类型注解出现的地方并检查,举个简单的例子:

    import checkers.nullness.quals.*;
    public class GetStarted {
        void sample() {
            @NonNull Object ref = new Object();
        }
    }
    
    

    使用javac编译上面的类

    javac -processor checkers.nullness.NullnessChecker GetStarted.java
    

编译是通过,但如果修改成
@NonNull Object ref = null;
再次编译,则出现

 GetStarted.java:5: incompatible types.
 found   : @Nullable <nulltype>
 required: @NonNull Object
         @NonNull Object ref = null;
                               ^
 1 error
 ````
 如果你不想使用类型注解检测出来错误,则不需要processor,直接javac GetStarted.java是可以编译通过的,这是在java 8 with Type Annotation Support版本里面可以,但java 5,6,7版本都不行,因为javac编译器不知道@NonNull是什么东西,但check framework 有个向下兼容的解决方案,就是将类型注解nonnull用/**/注释起来
,比如上面例子修改为
 ```java
 import checkers.nullness.quals.*;
 public class GetStarted {
     void sample() {
         /*@NonNull*/ Object ref = null;
     }
 }
 ```
 这样javac编译器就会忽略掉注释块,但用check framework里面的javac编译器同样能够检测出nonnull错误。
通过类型注解+check framework我们可以看到,现在runtime error可以在编译时候就能找到。


**参考**  
1. http://blog.csdn.net/sun_promise/article/details/51315032  
2. https://my.oschina.net/benhaile/blog/179642   


源代码地址:http://git.oschina.net/johnny/java_base
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值