カスタム注釈のコンパイル時注釈(RetentionPolicy.CLASS)(3):共通インタフェースの説明

20338 ワード

原http://blog.csdn.net/github_35180164/article/details/52171135
コンパイル時の注釈の使用方法について説明したが,ここでは注釈プロセッサ開発におけるいくつかの一般的なクラス,インタフェースの使用方法,概念について補足する.
ElementとTypeMirrorこの2つは注釈プロセッサを開発する上で最も重要な2つの概念だと思います.この2つの概念と使用を理解する必要があります.どちらもインタフェースです.まずElementの定義を見てみましょう.
/** 
 *         ,   、     ,        : 
 * ExecutableElement:           、          (     ),         ; 
 * PackageElement:         ; 
 * TypeElement:            ; 
 * TypeParameterElement:     、  、                ; 
 * VariableElement:      、enum   、         、          
 */  
public interface Element extends AnnotatedConstruct {  
    /** 
     *            
     *   ,        C,        C 
     */  
    TypeMirror asType();  
  
    /** 
     *         : 、 、  、  、  ...,      
     * 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 getModifiers();  
  
    /** 
     *           ,   
     *      java.util.Set        "Set"; 
     *               ,        ; 
     *            ,      ""; 
     *               ,      ""; 
     *                    ,         
     */  
    Name getSimpleName();  
  
    /** 
     *              。 
     *                           ,         ; 
     *           ,      ; 
     *          ,    null; 
     *             ,    null. 
     */  
    Element getEnclosingElement();  
  
    /** 
     *               
     */  
    List extends Element> getEnclosedElements();  
  
    /** 
     *                
     *         ,    getAllAnnotationMirrors 
     */  
    @Override  
    List extends AnnotationMirror> getAnnotationMirrors();  
  
    /** 
     *               (         ),     null。        ,               
     */  
    @Override  
    A getAnnotation(ClassannotationType);  
}

Elementはプログラムの要素を表し、注釈処理中にコンパイラはすべてのJavaソースファイルをスキャンし、ソースコードの各部分を特定のタイプのElementと見なします.パッケージ、クラス、インタフェース、メソッド、フィールドなど多くの要素の種類を表すことができます.具体的にはgetKind()メソッドで指定されている種類を参照してください.各Elementは静的で言語レベルのコンポーネントを表します.Elementには、次のような特定のタイプの要素を表す5つの直接サブインタフェースがあります.
PackageElementはパッケージ要素を表します
TypeElementはクラスまたはインタフェースのプログラム要素を表します.
VariableElementは、フィールド、enum定数、メソッド、または構築メソッドパラメータ、ローカル変数、または例外パラメータを表します.
ExecutableElementは、注釈タイプ要素を含むクラスまたはインタフェースのメソッド、構築メソッド、または初期化プログラム(静的またはインスタンス)を表します.
TypeParameterElementは、一般クラス、インタフェース、メソッド、または構築メソッド要素の汎用パラメータを表します.
開発においてElementは、実際の状況に応じて以上の5つのうちの1つに強く転換することができ、それぞれ独自の方法を持っており、簡単な例を見てみましょう.
ackage com.example;        // PackageElement  
  
import java.util.List;  
  
public class Sample         // TypeElement  
         {  // TypeParameterElement  
  
    private int num;        // VariableElement  
    String name;            // VariableElement  
  
    public Sample() {}      // ExecuteableElement  
  
    public void setName(    // ExecuteableElement  
            String name     // VariableElement  
            ) {}  
}  

ソースコードの各セクションはElementとして機能し、Type Elementはより具体的なタイプの要素に対応しています.上記の表から分かるように、1つの特定の要素は一般的に1つの要素の種類(ElementKind)を指すだけでなく、例えばTypeElementはクラスまたはインタフェースを指すことができ、1つの要素の正確な種類を知るにはgetKind()メソッドを呼び出す必要があり、この方法は1つのElementKind列挙値を返して具体的な種類を表す.
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;  
}  

上の管ElementKindは元素の種類と呼ばれています.元素のタイプTypeMirrorと混同しやすいからです.TypeMirrorは、Javaプログラミング言語のタイプを表します.たとえば、上記の例のフィールドString nameのように、要素の種類はFIELDであり、その要素のタイプはDECLAREDのクラスタイプを表します.ここで、Javaプログラミング言語のタイプはjava.lang.Stringです.Elementはソースコード上の要素を表し、TypeMirrorはElement対応Javaプログラミング言語のタイプを表します.
/** 
 *    Java          
 */  
public interface TypeMirror {  
    /** 
     *         ,   TypeKind    : 
     */  
    TypeKind getKind();  
} 

TypeMirrorはElementと同様にgetKind()メソッドを使用して特定のタイプを取得し、メソッドは列挙値を返します.次のようにします.
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;  
}  

ElementKindが記述したものとは異なる態様が見られる.このように説明するのがはっきりしていないことを知らないで、実はこのような概念の上のものは自分で何度使ってもっとよく理解することができて、これはこれと言います.
Elementの直接サブインタフェースここでは5つのElementサブインタフェースの一般的な方法を列挙し、大部分の説明はJDK PAIマニュアルから切り取る.これも一度に読む必要はありません.大体理解して、必要なときにこのようなものがあることを知っていればいいです.TypeElement
/** 
 *              
 */  
public interface TypeElement {  
  
    /** 
     *              
     *             (nesting kind)。          :top-level(  )、member(  )、local(  )  anonymous(  ) 
     */  
    NestingKind getNestingKind();  
  
    /** 
     *               。     ,       。                ,       . 
     *                        。  ,   java.util.Set          "java.util.Set" 
     */  
    Name getQualifiedName();  
  
    /** 
     *             。                 java.lang.Object,         NONE   NoType 
     */  
    TypeMirror getSuperclass();  
  
    /** 
     *                         
     */  
    List extends TypeMirror> getInterfaces();  
  
    /** 
     *                      
     */  
    List extends TypeParameterElement> getTypeParameters();  
} 

PackageElement
/** 
 *          . 
 */  
public interface PackageElement {  
  
    /** 
     *            。            
     */  
    Name getQualifiedName();  
  
    /** 
     *             ,    true,     false 
     */  
    boolean isUnnamed();  
}  

ExecutableElement
/** 
 *            、          (     ),         
 */  
public interface ExecutableElement {  
  
    /** 
     *                    
     */  
    List extends TypeParameterElement> getTypeParameters();  
  
    /** 
     *           
     */  
    TypeMirror getReturnType();  
  
    /** 
     *        
     */  
    List extends VariableElement> getParameters();  
  
    /** 
     *                    ,    true,     false 
     */  
    boolean isVarArgs();  
  
    /** 
     *                  throws              throwable 
     */  
    List extends TypeMirror> getThrownTypes();  
  
    /** 
     *     executable          ,      。             ,                  ,    null 
     */  
    AnnotationValue getDefaultValue();  
}

VariableElement
/** 
 *       、enum   、         、          
 */  
public interface VariableElement {  
  
    /** 
     *                     static final   ,        。     null。 
     *          String,         ,             (   Integer)。 
     *   ,      static final          。   ,enum              。        ,              String 
     */  
    Object getConstantValue();  
}  

TypeParameterElement
/** 
 *      、  、              . 
 */  
public interface TypeParameterElement {  
  
    /** 
     *                、  、        
     */  
    Element getGenericElement();  
  
    /** 
     *           。              extends         。 
     *           extends   ,    java.lang.Object        
     */  
    List extends TypeMirror> getBounds();  
}

注釈プロセッサの補助インタフェースは、カスタム注釈プロセッサの初期化インタフェースで、以下の4つの補助インタフェースを得ることができます.
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();  
    }  
}  

Filerは以前に使用しましたが、JavaPoetと組み合わせて必要な.javaファイルを生成するのが一般的です.ここでは使用しません.Messager Messagerは、注釈プロセッサにエラー、警告、プロンプト情報を報告する方法を提供します.これは、注釈プロセッサ開発者のログツールではなく、この注釈器を使用するサードパーティ開発者に情報を書くために使用されます.公式ドキュメントに記載されているメッセージの異なるレベルで非常に重要なのはKind.ERRORです.このタイプの情報は、私たちの注釈プロセッサの処理が失敗したことを示すために使用されます.サードパーティ開発者が注釈を誤って使用した可能性が高い.この概念は従来のJavaアプリケーションとは少し異なり、従来のJavaアプリケーションでは異常Exceptionを投げ出す可能性があります.プロセス()で例外を投げ出すと、注釈プロセッサを実行するJVMがクラッシュし(他のJavaアプリケーションのように)、私たちの注釈プロセッサを使用するサードパーティの開発者はjavacから注釈プロセッサのスタックトラッキング(Stacktace)情報を含むため、非常に分かりにくいエラー情報を得ることができます.そのため、注釈プロセッサにはMessagerクラスがあり、非常に美しいエラー情報を印刷することができます.また、エラーの要素に接続することもできます.現在のIDE(統合開発環境)のように、サードパーティ開発者はエラー情報を直接クリックすることができ、IDEはサードパーティ開発者プロジェクトのエラーのソースファイルの対応する行に直接ジャンプします.インタフェースコードを見てください.
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);  
}  

方法はよくわかりますが、主に印刷の情報タイプと記述文字列を指定する必要があります.Types TypesはTypeMirrorを処理するためのツールです.コードを見ればいいです.提供する方法は以下の通りです.
/** 
 *       TypeMirror    
 */  
public interface Types {  
    /** 
     *           。       DeclaredType   TypeVariable。           ,    null. 
     */  
    Element asElement(TypeMirror t);  
  
    /** 
     *      TypeMirror           . 
     *   :                  ,         false 
     */  
    boolean isSameType(TypeMirror t1, TypeMirror t2);  
  
    /** 
     *                   。                . 
     * 
     * @return                        true 
     * @throws IllegalArgumentException        executable   package    
     */  
    boolean isSubtype(TypeMirror t1, TypeMirror t2);  
  
    /** 
     *                   . 
     * 
     * @return                        true 
     * @throws IllegalArgumentException        executable   package    
     */  
    boolean isAssignable(TypeMirror t1, TypeMirror t2);  
  
    /** 
     *                     . 
     * 
     * @return                     true 
     * @throws IllegalArgumentException        executable   package    
     */  
    boolean contains(TypeMirror t1, TypeMirror t2);  
  
    /** 
     *                      . 
     * 
     * @return                        true 
     */  
    boolean isSubsignature(ExecutableType m1, ExecutableType m2);  
  
    /** 
     *           。interface            (   ). 
     * 
     * @return      ;    ,         
     * @throws IllegalArgumentException        executable   package    
     */  
    List extends TypeMirror> directSupertypes(TypeMirror t);  
  
    /** 
     *          . 
     * 
     * @return           
     * @throws IllegalArgumentException        package    
     */  
    TypeMirror erasure(TypeMirror t);  
  
    /** 
     *             (boxed)      。    boxing   . 
     * 
     * @param p           
     * @return    p          
     */  
    TypeElement boxedClass(PrimitiveType p);  
  
    /** 
     *           (unboxed)    (    )。    unboxing   . 
     * 
     * @param t         
     * @return    t        
     * @throws IllegalArgumentException            unboxing    
     */  
    PrimitiveType unboxedType(TypeMirror t);  
  
    /** 
     *       capture   . 
     * 
     * @return    capture       
     * @throws IllegalArgumentException      executable   package    
     */  
    TypeMirror capture(TypeMirror t);  
  
    /** 
     *       . 
     * 
     * @param kind              
     * @return        
     * @throws IllegalArgumentException    kind        
     */  
    PrimitiveType getPrimitiveType(TypeKind kind);  
  
    /** 
     *    null   。     null    . 
     */  
    NullType getNullType();  
  
    /** 
     *                     。 
     *              VOID   NONE。   ,     Elements.getPackageElement(CharSequence).asType()   . 
     * 
     * @param kind            
     * @return    VOID   NONE      
     * @throws IllegalArgumentException    kind    
     */  
    NoType getNoType(TypeKind kind);  
  
    /** 
     *                . 
     * 
     * @throws IllegalArgumentException              
     */  
    ArrayType getArrayType(TypeMirror componentType);  
  
    /** 
     *            。             ,       ,      . 
     * 
     * @param extendsBound    ( )  ;    ,      null 
     * @param superBound     ( )  ;    ,      null 
     * @return       
     * @throws IllegalArgumentException        
     */  
    WildcardType getWildcardType(TypeMirror extendsBound,  
                                 TypeMirror superBound);  
  
    /** 
     *                    。  ,     Set        String      ,                 Set. 
     * 
     *                          ,     0。     0,         ,             . 
     * 
     *            ,                 。 
     *   ,            Outer,     getDeclaredType(DeclaredType, TypeElement, TypeMirror...), 
     *           Outer.Inner. 
     * 
     * @param typeElem       
     * @param typeArgs         
     * @return                   
     * @throws IllegalArgumentException               ,                  
     */  
    DeclaredType getDeclaredType(TypeElement typeElem, TypeMirror... typeArgs);  
  
    /** 
     *          ,                   (           ).     
     *               ,             typeElem           。 
     *             ,    null,        getDeclaredType(typeElem, typeArgs). 
     * 
     * @param containing      ;    ,      null 
     * @param typeElem       
     * @param typeArgs         
     * @return                  ,            
     * @throws IllegalArgumentException               ,             、          
     */  
    DeclaredType getDeclaredType(DeclaredType containing,  
                                 TypeElement typeElem, TypeMirror... typeArgs);  
  
    /** 
     *                          ,        。 
     *   ,         Set     ,Set.add          String   ExecutableType. 
     * 
     * @param containing       
     * @param element        
     * @return               
     * @throws IllegalArgumentException              
     */  
    TypeMirror asMemberOf(DeclaredType containing, Element element);  
}  

Elements Elementsは、Elementを処理するためのツールです.次の方法があります.
/** 
 *       Element    
 */  
public interface Elements {  
  
    /** 
     *               . 
     * 
     * @param name          ;       ,     "" 
     * @return     ;          ,    null 
     */  
    PackageElement getPackageElement(CharSequence name);  
  
    /** 
     *                . 
     * 
     * @param name       
     * @return        ;           ,    null 
     */  
    TypeElement getTypeElement(CharSequence name);  
  
    /** 
     *         ,     . 
     *             ,              。                 ,                。 
     *                     
     * 
     * @see AnnotationMirror#getElementValues() 
     * @param a         
     * @return       ,      
     */  
    Map extends ExecutableElement, ? extends AnnotationValue>  
    getElementValuesWithDefaults(AnnotationMirror a);  
  
    /** 
     *        ("Javadoc")     
     * 
     * @param e          
     * @return        ;    ,    null 
     */  
    String getDocComment(Element e);  
  
    /** 
     *        ,    true,     false. 
     * 
     * @param e          
     * @return        ,    true,     false 
     */  
    boolean isDeprecated(Element e);  
  
    /** 
     *             . 
     * 
     * @param type            
     * @return       
     */  
    Name getBinaryName(TypeElement type);  
  
    /** 
     *       。       . 
     * 
     * @param type         
     * @return      
     */  
    PackageElement getPackageOf(Element type);  
  
    /** 
     *            ,             。     ,          ,           . 
     * 
     *   ,   ElementFilter                . 
     * 
     * @param type          
     * @return         
     */  
    List extends Element> getAllMembers(TypeElement type);  
  
    /** 
     *          ,             . 
     * 
     * @param e          
     * @return         
     */  
    List extends AnnotationMirror> getAllAnnotationMirrors(Element e);  
  
    /** 
     *       、               、     . 
     * 
     * @param hider         
     * @param hidden        
     * @return                      true 
     */  
    boolean hides(Element hider, Element hidden);  
  
    /** 
     *       (         )          。             ,              . 
     * 
     * @param overrider       ,    overrider 
     * @param overridden       ,      
     * @param type                
     * @return                     true 
     */  
    boolean overrides(ExecutableElement overrider, ExecutableElement overridden,  
                      TypeElement type);  
  
    /** 
     *                     。                        . 
     * 
     * @param value          
     * @return          
     * @throws IllegalArgumentException               
     * 
     * @see VariableElement#getConstantValue() 
     */  
    String getConstantExpression(Object value);  
  
    /** 
     *                    writer。           。                    . 
     * 
     * @param w        writer 
     * @param elements        
     */  
    void printElements(java.io.Writer w, Element... elements);  
  
    /** 
     *                 . 
     * 
     * @param cs               
     * @return                  
     */  
    Name getName(CharSequence cs);  
  
    /** 
     *                true,     false 
     * 
     * @param type         
     * @return                true,     false 
     * @since 1.8 
     */  
    boolean isFunctionalInterface(TypeElement type);  
}