1. 程式人生 > >@Target元註解的使用

@Target元註解的使用

@Target註解標記另外的註解用於限制此註解可以應用哪種Java元素型別。
先看Java SE 8中@Target是如何宣告的:

package java.lang.annotation;

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.lang.annotation.ElementType此列舉類聲明瞭有哪些Java元素型別:
java.lang.annotation.ElementType.TYPE:類、介面(包括註解型別)和列舉的宣告
java.lang.annotation.ElementType.FIELD:欄位宣告(包括列舉常量)
java.lang.annotation.ElementType.METHOD:方法宣告
java.lang.annotation.ElementType.PARAMETER:引數宣告
java.lang.annotation.ElementType.CONSTRUCTOR:建構函式宣告
java.lang.annotation.ElementType.LOCAL_VARIABLE:本地變數宣告
java.lang.annotation.ElementType.ANNOTATION_TYPE:註解型別宣告
java.lang.annotation.ElementType.PACKAGE:包宣告
java.lang.annotation.ElementType.TYPE_PARAMETER:型別引數宣告,JavaSE8引進,可以應用於類的泛型宣告之處
java.lang.annotation.ElementType.TYPE_USE:JavaSE8引進,此型別包括型別宣告和型別引數宣告,是為了方便設計者進行型別檢查,例如,如果使用@Target(ElementType.TYPE_USE)對@NonNull進行標記,則型別檢查器可以將@NonNull class C {...} C類的所有變數都視為非null
以下我們看看ElementType.TYPE_PARAMETER和ElementType.TYPE_USE的使用示例,對於其他的ElementType註解元素,看其說明就知道怎麼用了:

宣告由ElementType.TYPE_PARAMETER標記的@NotEmpty註解:

package org.springmorning.demo.javabase.annotation.meta;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
 * @author 春晨
 * Copyright ©2019 春晨 https://www.cnblogs.com/springmorning/p/10264624.html
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE_PARAMETER)
public @interface NotEmpty {
}

宣告由ElementType.TYPE_USE標記的@NotEmpty註解:

 
package org.springmorning.demo.javabase.annotation.meta;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
 * @author 春晨
 * Copyright ©2019 春晨 https://www.cnblogs.com/springmorning/p/10264624.html
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE_USE)
public @interface NotNull {
}

以下示例程式碼說明了兩種Target註解元素的使用區別,ElementType.TYPE_USE包含了ElementType.TYPE和ElementType.TYPE_PARAMETER

package org.springmorning.demo.javabase.annotation.meta;

/**
 * @author 春晨
 * Copyright ©2019 春晨 https://www.cnblogs.com/springmorning/p/10264624.html
 */

import java.util.ArrayList;

//泛型型別宣告時,使用TYPE_USE型別,編譯通過
class A <@NotNull TT>{}

//泛型型別宣告時,使用使用TYPE_PARAMETER型別,編譯通過
public class TypeParameterAndTypeUseAnnotation<@NotEmpty T>{

    //使用TYPE_PARAMETER型別,會編譯不通過
//    public void test(@NotEmpty T a){
//        new ArrayList<@NotEmpty String>();
//    }
    
    //使用TYPE_USE型別,編譯通過
    public void test(@NotNull T a){
        new ArrayList<@NotNull String>();
    }
}