JavaSE進(jìn)階

2、類(lèi)型注解

JDK1.8之后,關(guān)于元注解@Target的參數(shù)類(lèi)型ElementType枚舉值多了兩個(gè):

public?enum?ElementType?{

????/** Class, interface (including annotation type), or enum declaration */

????TYPE,

????/** Field declaration (includes enum constants) */

????FIELD,

????/** Method declaration */

????METHOD,

????/** Formal parameter declaration */

????PARAMETER,

????/** Constructor declaration */

????CONSTRUCTOR,

????/** Local variable declaration */

????LOCAL_VARIABLE,

????/** Annotation type declaration */

????ANNOTATION_TYPE,

????/** Package declaration */

????PACKAGE,

????/**

?????* Type parameter declaration

?????*

?????* @since?1.8

?????*/

????TYPE_PARAMETER,

????/**

?????* Use of a type

?????*

?????* @since?1.8

?????*/

????TYPE_USE

}

在java 8之前,注解只能是在聲明的地方所使用,java8開(kāi)始,注解可以應(yīng)用在任何地方。

ElementType.TYPE_PARAMETER 表示該注解能寫(xiě)在類(lèi)型變量的聲明語(yǔ)句中(eg:泛型聲明)。

ElementType.TYPE_USE 表示該注解能寫(xiě)在使用類(lèi)型的任何語(yǔ)句中。

package?com.atguigu.anno;

import?java.lang.annotation.ElementType;

import?java.lang.annotation.Target;

public?class?TestTypeDefine<@TypeDefine() U> {

private?U?u;

public?<@TypeDefine() T> void?test(T t){

}

}

@Target({ElementType.TYPE_PARAMETER})

@interface?TypeDefine{

}

package com.atguigu.anno;

import java.lang.annotation.ElementType;

import java.lang.annotation.Target;

@MyAnnotation

public class TestAnnotation<U>{

@MyAnnotation

private String name;

public static void main(String[] args) {

TestAnnotation <@MyAnnotation String> t = null;

int a = (@MyAnnotation int)2L;

@MyAnnotation int b = 10;

}

public static <@MyAnnotation T> void method(T t){

}

public static void test(@MyAnnotation String arg)throws @MyAnnotation Exception{

}

}

@Target(ElementType.TYPE_USE)

@interface MyAnnotation{

}

類(lèi)型注解被用來(lái)支持在Java的程序中做強(qiáng)類(lèi)型檢查。配合第三方插件工具Checker Framework(使用Checker Framework可以找到類(lèi)型注解出現(xiàn)的地方并檢查),可以在編譯的時(shí)候檢測(cè)出runtime error(eg:UnsupportedOperationException; NumberFormatException;NullPointerException異常等都是runtime error),以提高代碼質(zhì)量。這就是類(lèi)型注解的作用。

package checker;

import org.checkerframework.checker.nullness.qual.NonNull;

public class TestChecker {

public static void main(String[] args) {

Object obj = null;

printNonNullToString(obj);

}

public static void printNonNullToString(@NonNull Object object) {

System.out.println(object.toString());

}

}

進(jìn)入源代碼目錄 ??通過(guò)javac編譯 ?-processor 后面接注釋處理流程

javac ?-processor org.checkerframework.checker.nullness.NullnessChecker TestChecker.java

警告處理

javac -Xbootclasspath/p:D:\software\eclipse\checker-framework-2.1.13\checker\dist\jdk8.jar -processor org.checkerframework.checker.nullness.NullnessChecker TestChecker.java

要配置classpath=.;%JAVA_HOME%/lib/dt.jar;%JAVA_HOME%/lib/tools.jar;D:\software\eclipse\checker-framework-2.1.13\checker\dist\checker.jar;D:\software\eclipse\checker-framework-2.1.13\checker\dist\checker-qual.jar;

注意java 5,6,7版本是不支持注解@NonNull,但checker framework 有個(gè)向下兼容的解決方案,就是將類(lèi)型注解@NonNull 用/**/注釋起來(lái)。

這樣javac編譯器就會(huì)忽略掉注釋塊,但用checker framework里面的javac編譯器同樣能夠檢測(cè)出@NonNull錯(cuò)誤。