深入理解编译注解(四)常用接口介绍
前言
今天猛然想起一個(gè)注解在使用上的問(wèn)題,就一直在網(wǎng)上搜索資料,問(wèn)題倒是沒(méi)解決,但是看到了一篇非常好的博客,正好是我這里缺少的,寫(xiě)的很不錯(cuò),所以直接轉(zhuǎn)載。
在之前的demo中,為了完成編譯注解的功能,我們引入了com.google.auto.service:auto-service:1.0-rc2,這篇博客就是重點(diǎn)介紹了里面的api。
原文博客鏈接:http://blog.csdn.net/github_35180164/article/details/52171135。
正文
Element和TypeMirror
我覺(jué)得這兩個(gè)是開(kāi)發(fā)注解處理器最重要的兩個(gè)概念,理解這兩個(gè)的概念和使用是非常有必要的。
這兩個(gè)都是接口,先來(lái)看一下Element的定義:
/** * 表示一個(gè)程序元素,比如包、類(lèi)或者方法,有如下幾種子接口: * ExecutableElement:表示某個(gè)類(lèi)或接口的方法、構(gòu)造方法或初始化程序(靜態(tài)或?qū)嵗?#xff09;,包括注解類(lèi)型元素 ; * PackageElement:表示一個(gè)包程序元素; * TypeElement:表示一個(gè)類(lèi)或接口程序元素; * TypeParameterElement:表示一般類(lèi)、接口、方法或構(gòu)造方法元素的形式類(lèi)型參數(shù); * VariableElement:表示一個(gè)字段、enum 常量、方法或構(gòu)造方法參數(shù)、局部變量或異常參數(shù) */ public interface Element extends AnnotatedConstruct { /** * 返回此元素定義的類(lèi)型 * 例如,對(duì)于一般類(lèi)元素 C<N extends Number>,返回參數(shù)化類(lèi)型 C<N> */ TypeMirror asType(); /** * 返回此元素的種類(lèi):包、類(lèi)、接口、方法、字段...,如下枚舉值 * PACKAGE, ENUM, CLASS, ANNOTATION_TYPE, INTERFACE, ENUM_CONSTANT, FIELD, PARAMETER, LOCAL_VARIABLE, EXCEPTION_PARAMETER, * METHOD, CONSTRUCTOR, STATIC_INIT, INSTANCE_INIT, TYPE_PARAMETER, OTHER, RESOURCE_VARIABLE; */ ElementKind getKind(); /** * 返回此元素的修飾符,如下枚舉值 * PUBLIC, PROTECTED, PRIVATE, ABSTRACT, DEFAULT, STATIC, FINAL, * TRANSIENT, VOLATILE, SYNCHRONIZED, NATIVE, STRICTFP; */ Set<Modifier> getModifiers(); /** * 返回此元素的簡(jiǎn)單名稱(chēng),例如 * 類(lèi)型元素 java.util.Set<E> 的簡(jiǎn)單名稱(chēng)是 "Set"; * 如果此元素表示一個(gè)未指定的包,則返回一個(gè)空名稱(chēng); * 如果它表示一個(gè)構(gòu)造方法,則返回名稱(chēng) "<init>"; * 如果它表示一個(gè)靜態(tài)初始化程序,則返回名稱(chēng) "<clinit>"; * 如果它表示一個(gè)匿名類(lèi)或者實(shí)例初始化程序,則返回一個(gè)空名稱(chēng) */ Name getSimpleName(); /** * 返回封裝此元素的最里層元素。 * 如果此元素的聲明在詞法上直接封裝在另一個(gè)元素的聲明中,則返回那個(gè)封裝元素; * 如果此元素是頂層類(lèi)型,則返回它的包; * 如果此元素是一個(gè)包,則返回 null; * 如果此元素是一個(gè)泛型參數(shù),則返回 null. */ Element getEnclosingElement(); /** * 返回此元素直接封裝的子元素 */ List<? extends Element> getEnclosedElements(); /** * 返回直接存在于此元素上的注解 * 要獲得繼承的注解,可使用 getAllAnnotationMirrors */ @Override List<? extends AnnotationMirror> getAnnotationMirrors(); /** * 返回此元素針對(duì)指定類(lèi)型的注解(如果存在這樣的注解),否則返回 null。注解可以是繼承的,也可以是直接存在于此元素上的 */ @Override <A extends Annotation> A getAnnotation(Class<A> annotationType); } 復(fù)制代碼Element 代表程序的元素,在注解處理過(guò)程中,編譯器會(huì)掃描所有的Java源文件,并將源碼中的每一個(gè)部分都看作特定類(lèi)型的 Element。它可以代表包、類(lèi)、接口、方法、字段等多種元素種類(lèi),具體看getKind()方法中所指代的種類(lèi),每個(gè)Element 代表一個(gè)靜態(tài)的、語(yǔ)言級(jí)別的構(gòu)件。
Element 有五個(gè)直接子接口,它們分別代表一種特定類(lèi)型的元素,如下:
PackageElement 表示一個(gè)包程序元素 TypeElement 表示一個(gè)類(lèi)或接口程序元素 VariableElement 表示一個(gè)字段、enum 常量、方法或構(gòu)造方法參數(shù)、局部變量或異常參數(shù) ExecutableElement 表示某個(gè)類(lèi)或接口的方法、構(gòu)造方法或初始化程序(靜態(tài)或?qū)嵗?#xff09;,包括注解類(lèi)型元素 TypeParameterElement 表示一般類(lèi)、接口、方法或構(gòu)造方法元素的泛型參數(shù)
在開(kāi)發(fā)中Element可根據(jù)實(shí)際情況強(qiáng)轉(zhuǎn)為以上5種中的一種,它們都帶有各自獨(dú)有的方法,來(lái)看個(gè)簡(jiǎn)單的例子:
package com.example; // PackageElement import java.util.List; public class Sample // TypeElement <T extends List> { // TypeParameterElement private int num; // VariableElement String name; // VariableElement public Sample() {} // ExecuteableElement public void setName( // ExecuteableElement String name // VariableElement ) {} } 復(fù)制代碼源碼中的每個(gè)部分都作為一個(gè)Element,而TypeElement對(duì)應(yīng)著一種更具體的類(lèi)型元素。根據(jù)上面的表格可以知道,一種特定的元素一般不止指代一種元素種類(lèi)(ElementKind),比如TypeElement可以指代類(lèi)或接口,要知道一個(gè)元素的準(zhǔn)確的種類(lèi)需要調(diào)用getKind()方法,該方法返回一個(gè)ElementKind枚舉值來(lái)表示具體種類(lèi),如下:
public enum ElementKind { /** A package. */ PACKAGE, /** An enum type. */ ENUM, /** A class not described by a more specific kind (like {@code ENUM}). */ CLASS, /** An annotation type. */ ANNOTATION_TYPE, /** An interface not described by a more specific kind */ INTERFACE, // Variables /** An enum constant. */ ENUM_CONSTANT, /** A field not described by a more specific kind */ FIELD, /** A parameter of a method or constructor. */ PARAMETER, /** A local variable. */ LOCAL_VARIABLE, /** A parameter of an exception handler. */ EXCEPTION_PARAMETER, // Executables /** A method. */ METHOD, /** A constructor. */ CONSTRUCTOR, /** A static initializer. */ STATIC_INIT, /** An instance initializer. */ INSTANCE_INIT, /** A type parameter. */ TYPE_PARAMETER, /** An implementation-reserved element. This is not the element you are looking for. */ OTHER, /** * A resource variable. * @since 1.7 */ RESOURCE_VARIABLE; } 復(fù)制代碼上面管ElementKind稱(chēng)作元素的種類(lèi),因?yàn)樗驮氐念?lèi)型TypeMirror很容易混掉。TypeMirror表示的是 Java 編程語(yǔ)言中的類(lèi)型,比如上面例子中的字段String name,它的元素種類(lèi)為FIELD,而它的元素類(lèi)型為DECLARED表示一個(gè)類(lèi)類(lèi)型,這里對(duì)應(yīng)Java 編程語(yǔ)言中的類(lèi)型為java.lang.String。Element代表的是源代碼上的元素,TypeMirror代表的是Element對(duì)應(yīng)Java 編程語(yǔ)言中的類(lèi)型。
/** * 表示 Java 編程語(yǔ)言中的類(lèi)型 */ public interface TypeMirror { /** * 返回此類(lèi)型的種類(lèi),一個(gè) TypeKind 枚舉值: */ TypeKind getKind(); } 復(fù)制代碼TypeMirror和Element一樣有一個(gè)getKind()方法來(lái)獲取具體的類(lèi)型,方法返回一個(gè)枚舉值,如下:
public enum TypeKind { /** The primitive type {@code boolean}. */ BOOLEAN, /** The primitive type {@code byte}. */ BYTE, /** The primitive type {@code short}. */ SHORT, /** The primitive type {@code int}. */ INT, /** The primitive type {@code long}. */ LONG, /** The primitive type {@code char}. */ CHAR, /** The primitive type {@code float}. */ FLOAT, /** The primitive type {@code double}. */ DOUBLE, /** The pseudo-type corresponding to the keyword {@code void}. */ VOID, /** A pseudo-type used where no actual type is appropriate. */ NONE, /** The null type. */ NULL, /** An array type. */ ARRAY, /** A class or interface type. */ DECLARED, /** A class or interface type that could not be resolved. */ ERROR, /** A type variable. */ TYPEVAR, /** A wildcard type argument. */ WILDCARD, /** A pseudo-type corresponding to a package element. */ PACKAGE, /** A method, constructor, or initializer. */ EXECUTABLE, /** An implementation-reserved type. This is not the type you are looking for. */ OTHER, /** A union type. */ UNION, /** An intersection type. */ INTERSECTION; } 復(fù)制代碼可以看到和ElementKind所描述的是不同的方面。不知道這樣說(shuō)明的清不清楚,其實(shí)這種概念上的東西自己用幾次會(huì)有更好理解,這東西就說(shuō)到這。
Element的直接子接口
這里列一下5個(gè)Element子接口常用方法,大部分描述是從JDK PAI手冊(cè)中截取。這東西你也沒(méi)必要一次看完,大概了解一下,等到需要用的時(shí)候能夠知道有這么個(gè)東西就行了。
/** * 表示一個(gè)類(lèi)或接口程序元素 */ public interface TypeElement { /** * 返回此類(lèi)型元素的嵌套種類(lèi) * 某一類(lèi)型元素的嵌套種類(lèi) (nesting kind)。類(lèi)型元素的種類(lèi)有四種:top-level(頂層)、member(成員)、local(局部)和 anonymous(匿名) */ NestingKind getNestingKind(); /** * 返回此類(lèi)型元素的完全限定名稱(chēng)。更準(zhǔn)確地說(shuō),返回規(guī)范 名稱(chēng)。對(duì)于沒(méi)有規(guī)范名稱(chēng)的局部類(lèi)和匿名類(lèi),返回一個(gè)空名稱(chēng). * 一般類(lèi)型的名稱(chēng)不包括對(duì)其形式類(lèi)型參數(shù)的任何引用。例如,接口 java.util.Set<E> 的完全限定名稱(chēng)是 "java.util.Set" */ Name getQualifiedName(); /** * 返回此類(lèi)型元素的直接超類(lèi)。如果此類(lèi)型元素表示一個(gè)接口或者類(lèi) java.lang.Object,則返回一個(gè)種類(lèi)為 NONE 的 NoType */ TypeMirror getSuperclass(); /** * 返回直接由此類(lèi)實(shí)現(xiàn)或直接由此接口擴(kuò)展的接口類(lèi)型 */ List<? extends TypeMirror> getInterfaces(); /** * 按照聲明順序返回此類(lèi)型元素的形式類(lèi)型參數(shù) */ List<? extends TypeParameterElement> getTypeParameters(); } 復(fù)制代碼PackageElement
/** * 表示一個(gè)包程序元素. */ public interface PackageElement { /** * 返回此包的完全限定名稱(chēng)。該名稱(chēng)也是包的規(guī)范名稱(chēng) */ Name getQualifiedName(); /** * 如果此包是一個(gè)未命名的包,則返回 true,否則返回 false */ boolean isUnnamed(); } 復(fù)制代碼ExecutableElement
/** * 表示某個(gè)類(lèi)或接口的方法、構(gòu)造方法或初始化程序(靜態(tài)或?qū)嵗?#xff09;,包括注解類(lèi)型元素 */ public interface ExecutableElement { /** * 獲取按照聲明順序返回形式類(lèi)型參數(shù)元素 */ List<? extends TypeParameterElement> getTypeParameters(); /** * 獲取返回的類(lèi)型元素 */ TypeMirror getReturnType(); /** * 獲取形參元素 */ List<? extends VariableElement> getParameters(); /** * 如果此方法或構(gòu)造方法接受可變數(shù)量的參數(shù),則返回 true,否則返回 false */ boolean isVarArgs(); /** * 按聲明順序返回此方法或構(gòu)造方法的 throws 子句中所列出的異常和其他 throwable */ List<? extends TypeMirror> getThrownTypes(); /** * 如果此 executable 是一個(gè)注解類(lèi)型元素,則返回默認(rèn)值。如果此方法不是注解類(lèi)型元素,或者它是一個(gè)沒(méi)有默認(rèn)值的注解類(lèi)型元素,則返回 null */ AnnotationValue getDefaultValue(); } 復(fù)制代碼VariableElement
/** * 表示一個(gè)字段、enum 常量、方法或構(gòu)造方法參數(shù)、局部變量或異常參數(shù) */ public interface VariableElement { /** * 如果此變量是一個(gè)被初始化為編譯時(shí)常量的 static final 字段,則返回此變量的值。否則返回 null。 * 該值為基本類(lèi)型或 String,如果該值為基本類(lèi)型,則它被包裝在適當(dāng)?shù)陌b類(lèi)中(比如 Integer)。 * 注意,并非所有的 static final 字段都將具有常量值。特別是,enum 常量不 被認(rèn)為是編譯時(shí)常量。要獲得一個(gè)常量值,字段的類(lèi)型必須是基本類(lèi)型或 String */ Object getConstantValue(); } 復(fù)制代碼TypeParameterElement
/** * 表示一般類(lèi)、接口、方法或構(gòu)造方法元素的泛型參數(shù). */ public interface TypeParameterElement { /** * 返回由此類(lèi)型參數(shù)參數(shù)化的一般類(lèi)、接口、方法或構(gòu)造方法 */ Element getGenericElement(); /** * 返回此類(lèi)型參數(shù)的邊界。它們是用來(lái)聲明此類(lèi)型參數(shù)的 extends 子句所指定的類(lèi)型。 * 如果沒(méi)有使用顯式的 extends 子句,則認(rèn)為 java.lang.Object 是唯一的邊界 */ List<? extends TypeMirror> getBounds(); } 復(fù)制代碼注解處理器的輔助接口
在自定義注解處理器的初始化接口,可以獲取到以下4個(gè)輔助接口:
public class MyProcessor extends AbstractProcessor { private Types typeUtils; private Elements elementUtils; private Filer filer; private Messager messager; @Override public synchronized void init(ProcessingEnvironment processingEnv) { super.init(processingEnv); typeUtils = processingEnv.getTypeUtils(); elementUtils = processingEnv.getElementUtils(); filer = processingEnv.getFiler(); messager = processingEnv.getMessager(); } } 復(fù)制代碼其中Filer之前有用過(guò),一般我們會(huì)用它配合JavaPoet來(lái)生成我們需要的.java文件,這里就不再提它的用法。
Messager
Messager提供給注解處理器一個(gè)報(bào)告錯(cuò)誤、警告以及提示信息的途徑。它不是注解處理器開(kāi)發(fā)者的日志工具,而是用來(lái)寫(xiě)一些信息給使用此注解器的第三方開(kāi)發(fā)者的。在官方文檔中描述了消息的不同級(jí)別中非常重要的是Kind.ERROR,因?yàn)檫@種類(lèi)型的信息用來(lái)表示我們的注解處理器處理失敗了。很有可能是第三方開(kāi)發(fā)者錯(cuò)誤的使用了注解。這個(gè)概念和傳統(tǒng)的Java應(yīng)用有點(diǎn)不一樣,在傳統(tǒng)Java應(yīng)用中我們可能就拋出一個(gè)異常Exception。如果你在process()中拋出一個(gè)異常,那么運(yùn)行注解處理器的JVM將會(huì)崩潰(就像其他Java應(yīng)用一樣),使用我們注解處理器第三方開(kāi)發(fā)者將會(huì)從javac中得到非常難懂的出錯(cuò)信息,因?yàn)樗⒔馓幚砥鞯亩褩8?#xff08;Stacktace)信息。因此,注解處理器就有一個(gè)Messager類(lèi),它能夠打印非常優(yōu)美的錯(cuò)誤信息。除此之外,你還可以連接到出錯(cuò)的元素。在像現(xiàn)在的IDE(集成開(kāi)發(fā)環(huán)境)中,第三方開(kāi)發(fā)者可以直接點(diǎn)擊錯(cuò)誤信息,IDE將會(huì)直接跳轉(zhuǎn)到第三方開(kāi)發(fā)者項(xiàng)目的出錯(cuò)的源文件的相應(yīng)的行。
看下接口代碼:
public interface Messager { void printMessage(Diagnostic.Kind kind, CharSequence msg); void printMessage(Diagnostic.Kind kind, CharSequence msg, Element e); void printMessage(Diagnostic.Kind kind, CharSequence msg, Element e, AnnotationMirror a); void printMessage(Diagnostic.Kind kind, CharSequence msg, Element e, AnnotationMirror a, AnnotationValue v); } 復(fù)制代碼方法都比較好懂,主要需要指定打印的信息類(lèi)型和描述字符串。
Types Types是一個(gè)用來(lái)處理TypeMirror的工具,看下代碼就好了,提供的方法如下:
/** * 一個(gè)用來(lái)處理TypeMirror的工具 */ public interface Types { /** * 返回對(duì)應(yīng)于類(lèi)型的元素。該類(lèi)型可能是 DeclaredType 或 TypeVariable。如果該類(lèi)型沒(méi)有對(duì)應(yīng)元素,則返回 null. */ Element asElement(TypeMirror t); /** * 測(cè)試兩個(gè) TypeMirror 對(duì)象是否表示同一類(lèi)型. * 警告:如果此方法兩個(gè)參數(shù)中有一個(gè)表示通配符,那么此方法將返回 false */ boolean isSameType(TypeMirror t1, TypeMirror t2); /** * 測(cè)試一種類(lèi)型是否是另一個(gè)類(lèi)型的子類(lèi)型。任何類(lèi)型都被認(rèn)為是其本身的子類(lèi)型. * * @return 當(dāng)且僅當(dāng)?shù)谝环N類(lèi)型是第二種類(lèi)型的子類(lèi)型時(shí)返回 true * @throws IllegalArgumentException 如果給定一個(gè) executable 或 package 類(lèi)型 */ boolean isSubtype(TypeMirror t1, TypeMirror t2); /** * 測(cè)試一種類(lèi)型是否可以指派給另一種類(lèi)型. * * @return 當(dāng)且僅當(dāng)?shù)谝环N類(lèi)型可以指派給第二種類(lèi)型時(shí)返回 true * @throws IllegalArgumentException 如果給定一個(gè) executable 或 package 類(lèi)型 */ boolean isAssignable(TypeMirror t1, TypeMirror t2); /** * 測(cè)試一個(gè)類(lèi)型參數(shù)是否包含 另一個(gè)類(lèi)型參數(shù). * * @return 當(dāng)且僅當(dāng)?shù)谝环N類(lèi)型包含第二種類(lèi)型時(shí)返回 true * @throws IllegalArgumentException 如果給定一個(gè) executable 或 package 類(lèi)型 */ boolean contains(TypeMirror t1, TypeMirror t2); /** * 測(cè)試一個(gè)方法的簽名是否是另一個(gè)方法的子簽名. * * @return 當(dāng)且僅當(dāng)?shù)谝粋€(gè)簽名是第二個(gè)簽名的子簽名時(shí)返回 true */ boolean isSubsignature(ExecutableType m1, ExecutableType m2); /** * 返回類(lèi)型的直接超類(lèi)型。interface 類(lèi)型將出現(xiàn)在列表的最后(如果有). * * @return 直接超類(lèi)型;如果沒(méi)有,則返回一個(gè)空列表 * @throws IllegalArgumentException 如果給定一個(gè) executable 或 package 類(lèi)型 */ List<? extends TypeMirror> directSupertypes(TypeMirror t); /** * 返回刪除狀態(tài)的類(lèi)型. * * @return 刪除狀態(tài)的給定類(lèi)型 * @throws IllegalArgumentException 如果給定一個(gè) package 類(lèi)型 */ TypeMirror erasure(TypeMirror t); /** * 返回給定基本類(lèi)型的裝箱 (boxed) 值類(lèi)型的類(lèi)。即應(yīng)用 boxing 轉(zhuǎn)換. * * @param p 要轉(zhuǎn)換的基本類(lèi)型 * @return 類(lèi)型 p 的裝箱值類(lèi)型的類(lèi) */ TypeElement boxedClass(PrimitiveType p); /** * 返回給定類(lèi)型的拆箱 (unboxed) 值類(lèi)型(基本類(lèi)型)。即應(yīng)用 unboxing 轉(zhuǎn)換. * * @param t 要拆箱的類(lèi)型 * @return 類(lèi)型 t 的拆箱值類(lèi)型 * @throws IllegalArgumentException 如果給定類(lèi)型無(wú)法進(jìn)行 unboxing 轉(zhuǎn)換 */ PrimitiveType unboxedType(TypeMirror t); /** * 對(duì)類(lèi)型應(yīng)用 capture 轉(zhuǎn)換. * * @return 應(yīng)用 capture 轉(zhuǎn)換的結(jié)果 * @throws IllegalArgumentException 如果給定 executable 或 package 類(lèi)型 */ TypeMirror capture(TypeMirror t); /** * 返回基本類(lèi)型. * * @param kind 要返回的基本類(lèi)型的種類(lèi) * @return 一個(gè)基本類(lèi)型 * @throws IllegalArgumentException 如果 kind 不是基本種類(lèi) */ PrimitiveType getPrimitiveType(TypeKind kind); /** * 返回 null 類(lèi)型。該類(lèi)型是 null 的類(lèi)型. */ NullType getNullType(); /** * 返回在實(shí)際類(lèi)型不適用的地方所使用的偽類(lèi)型。 * 要返回的類(lèi)型的種類(lèi)可以是 VOID 或 NONE。對(duì)于包,可以使用 Elements.getPackageElement(CharSequence).asType() 替代. * * @param kind 要返回的類(lèi)型的種類(lèi) * @return 種類(lèi) VOID 或 NONE 的偽類(lèi)型 * @throws IllegalArgumentException 如果 kind 無(wú)效 */ NoType getNoType(TypeKind kind); /** * 返回具有指定組件類(lèi)型的數(shù)組類(lèi)型. * * @throws IllegalArgumentException 如果組件類(lèi)型對(duì)于數(shù)組無(wú)效 */ ArrayType getArrayType(TypeMirror componentType); /** * 返回新的通配符類(lèi)型參數(shù)。可以指定通配符邊界中的一個(gè),也可以都不指定,但不能都指定. * * @param extendsBound 擴(kuò)展(上)邊界;如果沒(méi)有,則該參數(shù)為 null * @param superBound 超(下)邊界;如果沒(méi)有,則該參數(shù)為 null * @return 新的通配符 * @throws IllegalArgumentException 如果邊界無(wú)效 */ WildcardType getWildcardType(TypeMirror extendsBound, TypeMirror superBound); /** * 返回對(duì)應(yīng)于類(lèi)型元素和實(shí)際類(lèi)型參數(shù)的類(lèi)型。例如,如果給定 Set 的類(lèi)型元素和 String 的類(lèi)型鏡像,那么可以使用此方法獲取參數(shù)化類(lèi)型 Set<String>. * * 類(lèi)型參數(shù)的數(shù)量必須等于類(lèi)型元素的形式類(lèi)型參數(shù)的數(shù)量,或者等于 0。如果等于 0,并且類(lèi)型元素是泛型,則返回該類(lèi)型元素的原始類(lèi)型. * * 如果返回一個(gè)參數(shù)化類(lèi)型,則其類(lèi)型元素不得包含在一般外部類(lèi)中。 * 例如,首先使用此方法獲取類(lèi)型 Outer<String>,然后調(diào)用 getDeclaredType(DeclaredType, TypeElement, TypeMirror...), * 可以構(gòu)造參數(shù)化類(lèi)型 Outer<String>.Inner<Number>. * * @param typeElem 類(lèi)型元素 * @param typeArgs 實(shí)際類(lèi)型參數(shù) * @return 對(duì)應(yīng)于類(lèi)型元素和實(shí)際類(lèi)型參數(shù)的類(lèi)型 * @throws IllegalArgumentException 如果給定的類(lèi)型參數(shù)太多或太少,或者提供不合適的類(lèi)型參數(shù)或類(lèi)型元素 */ DeclaredType getDeclaredType(TypeElement typeElem, TypeMirror... typeArgs); /** * 根據(jù)給定的包含類(lèi)型,返回對(duì)應(yīng)于類(lèi)型元素和實(shí)際類(lèi)型參數(shù)的類(lèi)型(它是給定包含類(lèi)型的成員).例子如上 * 如果包含類(lèi)型是一個(gè)參數(shù)化類(lèi)型,則類(lèi)型參數(shù)的數(shù)量必須等于 typeElem 的形式類(lèi)型參數(shù)的數(shù)量。 * 如果包含類(lèi)型不是參數(shù)化的,或者為 null,則此方法等效于 getDeclaredType(typeElem, typeArgs). * * @param containing 包含類(lèi)型;如果沒(méi)有,則該參數(shù)為 null * @param typeElem 類(lèi)型元素 * @param typeArgs 實(shí)際類(lèi)型參數(shù) * @return 對(duì)應(yīng)于類(lèi)型元素和實(shí)際類(lèi)型參數(shù)的類(lèi)型,該類(lèi)型包含在給定類(lèi)型中 * @throws IllegalArgumentException 如果給定的類(lèi)型參數(shù)太多或太少,或者提供了不合適的類(lèi)型參數(shù)、類(lèi)型元素或包含類(lèi)型 */ DeclaredType getDeclaredType(DeclaredType containing, TypeElement typeElem, TypeMirror... typeArgs); /** * 當(dāng)元素被視為給定類(lèi)型的成員或者直接由給定類(lèi)型包含時(shí),返回該元素的類(lèi)型。 * 例如,被視為參數(shù)化類(lèi)型 Set<String> 的成員時(shí),Set.add 方法是參數(shù)類(lèi)型為 String 的 ExecutableType. * * @param containing 包含類(lèi)型 * @param element 元素 * @return 從包含類(lèi)型來(lái)看的元素的類(lèi)型 * @throws IllegalArgumentException 如果元素對(duì)于給定類(lèi)型無(wú)效 */ TypeMirror asMemberOf(DeclaredType containing, Element element); } 復(fù)制代碼Elements Elements是一個(gè)用來(lái)處理Element的工具,提供的方法如下:
/** * 一個(gè)用來(lái)處理Element的工具 */ public interface Elements { /** * 返回已給出其完全限定名稱(chēng)的包. * * @param name 完全限定的包名稱(chēng);對(duì)于未命名的包,該參數(shù)為 "" * @return 指定的包;如果沒(méi)有找到這樣的包,則返回 null */ PackageElement getPackageElement(CharSequence name); /** * 返回已給出其規(guī)范名稱(chēng)的類(lèi)型元素. * * @param name 規(guī)范名稱(chēng) * @return 指定的類(lèi)型元素;如果沒(méi)有找到這樣的元素,則返回 null */ TypeElement getTypeElement(CharSequence name); /** * 返回注釋元素的值,包括默認(rèn)值. * 此值是以映射的形式返回的,該映射將元素與其相應(yīng)的值關(guān)聯(lián)。只包括那些注釋中明確存在其值的元素,不包括那些隱式假定其默認(rèn)值的元素。 * 映射的順序與值出現(xiàn)在注釋源中的順序匹配 * * @see AnnotationMirror#getElementValues() * @param a 要檢查的注釋 * @return 注釋元素的值,包括默認(rèn)值 */ Map<? extends ExecutableElement, ? extends AnnotationValue> getElementValuesWithDefaults(AnnotationMirror a); /** * 返回元素的文檔("Javadoc")注釋文本 * * @param e 將被檢查的元素 * @return 元素的文檔注釋;如果沒(méi)有,則返回 null */ String getDocComment(Element e); /** * 如果元素已過(guò)時(shí),則返回 true,否則返回 false. * * @param e 將被檢查的元素 * @return 如果元素已過(guò)時(shí),則返回 true,否則返回 false */ boolean isDeprecated(Element e); /** * 返回類(lèi)型元素的二進(jìn)制名稱(chēng). * * @param type 將被檢查的類(lèi)型元素 * @return 二進(jìn)制名稱(chēng) */ Name getBinaryName(TypeElement type); /** * 返回元素的包。包的包是它本身. * * @param type 將被檢查的元素 * @return 元素的包 */ PackageElement getPackageOf(Element type); /** * 返回類(lèi)型元素的所有成員,不管是繼承的還是直接聲明的。對(duì)于一個(gè)類(lèi),結(jié)果還包括其構(gòu)造方法,但不包括局部類(lèi)或匿名類(lèi). * * 注意,使用 ElementFilter 中的方法可以隔離某個(gè)種類(lèi)的元素. * * @param type 將被檢查的類(lèi)型 * @return 類(lèi)型的所有成員 */ List<? extends Element> getAllMembers(TypeElement type); /** * 返回元素的所有注釋,不管是繼承的還是直接存在的. * * @param e 將被檢查的元素 * @return 元素的所有注釋 */ List<? extends AnnotationMirror> getAllAnnotationMirrors(Element e); /** * 測(cè)試一個(gè)類(lèi)型、方法或字段是否隱藏了另一個(gè)類(lèi)型、方法或字段. * * @param hider 第一個(gè)元素 * @param hidden 第二個(gè)元素 * @return 當(dāng)且僅當(dāng)?shù)谝粋€(gè)元素隱藏了第二個(gè)元素時(shí)返回 true */ boolean hides(Element hider, Element hidden); /** * 測(cè)試一個(gè)方法(作為給定類(lèi)型的成員)是否重寫(xiě)了另一個(gè)方法。當(dāng)非抽象方法重寫(xiě)抽象方法時(shí),還可以說(shuō)成是前者實(shí)現(xiàn) 了后者. * * @param overrider 第一個(gè)方法,可能是 overrider * @param overridden 第二個(gè)方法,可能被重寫(xiě) * @param type 第一個(gè)方法是其成員的類(lèi)型 * @return 當(dāng)且僅當(dāng)?shù)谝粋€(gè)方法重寫(xiě)第二個(gè)方法時(shí)返回 true */ boolean overrides(ExecutableElement overrider, ExecutableElement overridden, TypeElement type); /** * 返回表示基本值或字符串的常量表達(dá)式 文本。返回文本的形式是一種適合于表示源代碼中的值的形式. * * @param value 基本值或字符串 * @return 常量表達(dá)式的文本 * @throws IllegalArgumentException 如果參數(shù)不是基本值或字符串 * * @see VariableElement#getConstantValue() */ String getConstantExpression(Object value); /** * 按指定順序?qū)⒃氐谋硎拘问酱蛴〉浇o定 writer。此方法的主要用途是診斷。輸出的具體格式?jīng)]有 指定并且是可以更改的. * * @param w 輸出打印到的 writer * @param elements 要打印的元素 */ void printElements(java.io.Writer w, Element... elements); /** * 返回與參數(shù)具有相同字符序列的名稱(chēng). * * @param cs 將以名稱(chēng)形式返回的字符序列 * @return 返回與參數(shù)具有相同字符序列的名稱(chēng) */ Name getName(CharSequence cs); /** * 如果類(lèi)型是一個(gè)泛型接口則返回 true,否則返回 false * * @param type 將被檢查的類(lèi)型 * @return 如果類(lèi)型是一個(gè)泛型接口則返回 true,否則返回 false * @since 1.8 */ boolean isFunctionalInterface(TypeElement type); } 復(fù)制代碼總結(jié)
篇幅稍微有點(diǎn)長(zhǎng),大家可以耐心的看,看完之后,對(duì)之前的demo的理解肯定又上升了一個(gè)水平。可能在復(fù)制的過(guò)程中,排版出現(xiàn)了一些變化,如果覺(jué)得不太美觀的話(huà),可以去查看原文。
總結(jié)
以上是生活随笔為你收集整理的深入理解编译注解(四)常用接口介绍的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 智慧城市:物联网安全需先行
- 下一篇: 有年味的年会才够味|第12届信息化领袖峰