重复注解与类型注解
基于尚硅谷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