@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>(); } }