javax.lang.model.element源码解析

11 篇文章 0 订阅

前言

本文解析javax.lang.model.element包中几个类的源码,看这部分的代码也是因为javac中实现了这部分的接口.类不多,如图:

1

解析

在解析之前,先来看下javax.lang.model包下的几个顶级接口, javax.lang.model.element包中有几个类是其子接口.

UnknownEntityException

表示未知类型的实体遇到的异常的超类。,如果语言有新的特性和新的结构类型出现,则这种情况可能会发生。访问者可能会抛出此异常的子类,以指示访问者是为该语言的先前版本创建的。

这些异常的公共超类允许单个catch块对代码进行统一处理。

该异常继承自RuntimeException.代码如下:

public class UnknownEntityException extends RuntimeException {

    private static final long serialVersionUID = 269L;

    /**
     * Creates a new {@code UnknownEntityException} with the specified
     * detail message.
     *
     * @param message the detail message
     */
    protected UnknownEntityException(String message) {
        super(message);
    }
}

SourceVersion

代表Java™ programming language的版本的枚举.有关特定版本的信息,请参阅对应版本Java版语言规范。

该类会随着java的不断发布来跟新该类.该类的代码如下:

public enum SourceVersion {
    /*
     * Summary of language evolution
     * 1.1: nested classes
     * 1.2: strictfp
     * 1.3: no changes
     * 1.4: assert
     * 1.5: annotations, generics, autoboxing, var-args...
     * 1.6: no changes
     * 1.7: diamond syntax, try-with-resources, etc.
     * 1.8: lambda expressions and default methods
     * java语言演变的清单摘要:
     * 1.1: 类嵌套
     * 1.2: 支持strictfp
     * 1.3: 没有变化
     * 1.4: 断言
     * 1.5: 注解,泛型,自动装箱,可变参数
     * 1.6: 没有变化
     * 1.7: diamond syntax, try-with-resources, etc.
     * 1.8: lambda 表达式,默认方法
     */

    /**
     * The original version.
     *
     * The language described in
     * <cite>The Java&trade; Language Specification, First Edition</cite>.
     * java语言的第一版,在The Java™ Language Specification第一版中有描述
     */
    RELEASE_0,

    /**
     * The version recognized by the Java Platform 1.1.
     *
     * The language is {@code RELEASE_0} augmented with nested classes as described in the 1.1 update to
     * <cite>The Java&trade; Language Specification, First Edition</cite>.
     * java 1.1 版本.
     * 该版本比在The Java™ Language Specification第一版中新增了嵌套类
     */
    RELEASE_1,

    /**
     * The version recognized by the Java 2 Platform, Standard Edition,
     * v 1.2.
     * java 1.2 版本
     *
     * The language described in
     * <cite>The Java&trade; Language Specification,
     * Second Edition</cite>, which includes the {@code
     * strictfp} modifier.
     * 该版本在The Java™ Language Specification第二版中有描述,该版本新增了strictfp修饰符
     */
    RELEASE_2,

    /**
     * The version recognized by the Java 2 Platform, Standard Edition,
     * v 1.3.
     *
     * No major changes from {@code RELEASE_2}.
     * 1.3 版本.和1.2相比没有变化
     */
    RELEASE_3,

    /**
     * The version recognized by the Java 2 Platform, Standard Edition,
     * v 1.4.
     *
     * Added a simple assertion facility.
     * 1.4版本.增加了断言机制
     */
    RELEASE_4,

    /**
     * The version recognized by the Java 2 Platform, Standard
     * Edition 5.0.
     *
     * The language described in
     * <cite>The Java&trade; Language Specification,
     * Third Edition</cite>.  First release to support
     * generics, annotations, autoboxing, var-args, enhanced {@code
     * for} loop, and hexadecimal floating-point literals.

     * java 2 Platform, Standard Edition 5.0--> jdk 1.5.
     * 在The Java™ Language Specification第三版中有描述.支持泛型,注解,可变参数
     * 增加for循环,16进制的浮点字面量
     * 
     */
    RELEASE_5,

    /**
     * The version recognized by the Java Platform, Standard Edition
     * 6.
     *
     * No major changes from {@code RELEASE_5}.
     * jdk1.6。 和jdk1.5没有任何变化
     */
    RELEASE_6,

    /**
     * The version recognized by the Java Platform, Standard Edition
     * 7.
     *
     * Additions in this release include, diamond syntax for
     * constructors, {@code try}-with-resources, strings in switch,
     * binary literals, and multi-catch.
     * @since 1.7
     * jdk 1.7. 支持diamond syntax,try-with-resources,switch支持string,
     * 二进制字面量,multi-catch
     */
    RELEASE_7,

    /**
     * The version recognized by the Java Platform, Standard Edition
     * 8.
     *
     * Additions in this release include lambda expressions and default methods.
     * @since 1.8
     * jdk 1.8.支持lambda 表达式,默认方法
     */
    RELEASE_8;

    // Note that when adding constants for newer releases, the
    // behavior of latest() and latestSupported() must be updated too.
    // 当有信版本对应的枚举添加到该类中时,对应的latest()和 latestSupported()方法的
    // 实现也应该进行修改,使其返回最新的版本对应的枚举

    /**
     * Returns the latest source version that can be modeled.
     * 返回最新的版本
     * @return the latest source version that can be modeled
     */
    public static SourceVersion latest() {
        return RELEASE_8;
    }

    private static final SourceVersion latestSupported = getLatestSupported();

    private static SourceVersion getLatestSupported() {
        try {
            String specVersion = System.getProperty("java.specification.version");

            if ("1.8".equals(specVersion))
                return RELEASE_8;
            else if("1.7".equals(specVersion))
                return RELEASE_7;
            else if("1.6".equals(specVersion))
                return RELEASE_6;
        } catch (SecurityException se) {}

        return RELEASE_5;
    }

    /**
     * Returns the latest source version fully supported by the
     * current execution environment.  {@code RELEASE_5} or later must
     * be returned.
     * 返回当前运行环境中完全支持的最新版本,返回值必须是RELEASE_5或者是最新版本
     *
     * @return the latest source version that is fully supported
     */
    public static SourceVersion latestSupported() {
        return latestSupported;
    }

    /**
     * 判断名称是否为最新源版本中的语法有效标识符(简单名称)或关键字.
     * 该方法只有在给定name的首字符在调用Character.isJavaIdentifierStart(int)时返回
     * true,同时接下来的字符在Character.isJavaIdentifierPart(int) 中返回true时,该
     * 方法才最终返回true.
     * 此方法对应常规标识符、关键字和文本“true”、“false”和“null"返回true。对于所有其他字符串返回false。
     *
     */
    public static boolean isIdentifier(CharSequence name) {
        String id = name.toString();

        if (id.length() == 0) {
            return false;
        }
        int cp = id.codePointAt(0);
        if (!Character.isJavaIdentifierStart(cp)) {
            return false;
        }
        for (int i = Character.charCount(cp);
                i < id.length();
                i += Character.charCount(cp)) {
            cp = id.codePointAt(i);
            if (!Character.isJavaIdentifierPart(cp)) {
                return false;
            }
        }
        return true;
    }

    /**
     * 判断名称是否是最新源代码中语法有效限定名.与isIdentifier()方法不同,
     * 对于关键字和字面量,该方法返回false
     */ 
    public static boolean isName(CharSequence name) {
        String id = name.toString();

        for(String s : id.split("\\.", -1)) {
            if (!isIdentifier(s) || isKeyword(s))
                return false;
        }
        return true;
    }

    // keywords 保存的是java语言最新版本的关键字
    private final static Set<String> keywords;
    static {
        Set<String> s = new HashSet<String>();
        String [] kws = {
            "abstract", "continue",     "for",          "new",          "switch",
            "assert",   "default",      "if",           "package",      "synchronized",
            "boolean",  "do",           "goto",         "private",      "this",
            "break",    "double",       "implements",   "protected",    "throw",
            "byte",     "else",         "import",       "public",       "throws",
            "case",     "enum",         "instanceof",   "return",       "transient",
            "catch",    "extends",      "int",          "short",        "try",
            "char",     "final",        "interface",    "static",       "void",
            "class",    "finally",      "long",         "strictfp",     "volatile",
            "const",    "float",        "native",       "super",        "while",
            // literals
            "null",     "true",         "false"
        };
        for(String kw : kws)
            s.add(kw);
        keywords = Collections.unmodifiableSet(s);
    }

    /**
     * 判断给定的字符串是否是Java最新版本的关键字或者是字面量
     */
    public static boolean isKeyword(CharSequence s) {
        String keywordOrLiteral = s.toString();
        return keywords.contains(keywordOrLiteral);
    }
}

这里,有些java语法中的特性是很少接触过的,或者对应的说法没有听过.这里就简要介绍一下.

  1. strictfp修饰符: 如果表达式的类型为float或double,那么就会有一个问题,该表达式的值到底是从哪个值集(详情,请看JLS 4.2.3节)中导出的,这由值集转换规则(JLS 5.1.13)决定,这些规则又一轮于该表达式是否是FP-严格的.每个常量表达式都是FP-严格的.如果表达式不是常量表达式,那么就会考虑包含该表达式的所有类声明,接口声明和方法声明.如果任何这种声明有strictfp修饰符,那么该表达式就是FP-严格的.(JLS 15.4)

  2. diamond syntax: 在jdk 1.7 之前,我们是这样写代码的:

    Map<Integer, Map<String, String>> usersLists =
    new HashMap<Integer, Map<String, String>>();

    jdk 1.7 之后呢,我们可以这样写:

    Map<Integer, Map<String, String>> usersLists = new HashMap<>();

AnnotatedConstruct

表示一个可以被注解的结构(元素),这个结构可以是元素和类型.

对应一个注解A来说,它有一个注解类型–>AT.如果该AT是可以重复的,那么该AT可以重复的注解类型就是ATC.

注解A直接声明在C上,如果是:

  • A 显示或者隐示的声明在C的源代码上.通过,如果一个注解出现在C所对应的源代码中,那么A就是显示的被应用于C.如果有多个AT类型的注解存在于C,那么如果该AT是可重复注解,那么就称ATC被隐式的声明在C上.
  • A 出现在C所对应的可执行文件中,类如类文件中的RuntimeVisibleAnnotations(运行时可见的注解) 和 RuntimeVisibleParameterAnnotations(运行时可见的参数注解)

注解A声明在C上,如果是:

  • 注解A直接声明在C上
  • AT注解没有声明在C上,同时C是一个类,同时AT是可以继承的,同时注解A出现在C的父类中

注解A间接的声明在C上,如果满足如下2点:

  • AT是一个可重复注解,其可重复的注解类型为ATC
  • ATC类型的注解直接声明在C上,同时A是该ATC注解中valu方法的返回值类型.

注解A与C是关联的,如果是:

  • A 直接或者间接的声明在C上
  • AT没有直接或者间接的声明在C上,同时C是一个类,同时AT是可继承的,同时A与C的父类是关联的.

关于这部分的内容,可以参阅 JLS 9.6,9.6.3.3

代码如下:

public interface AnnotatedConstruct {
    /**
      *  返回直接声明在该结构上的注解.
      *  如果没有直接声明的注解,则返回空集合.    
      *  关于AnnotationMirror,在后面会有介绍
     */
    List<? extends AnnotationMirror> getAnnotationMirrors();

    /**
      *  返回指定类型所对应的注解,如果不存在,则返回null.
      *  注解的返回值可能会包含指定类型的class的元素.这个class不能直接返回:
      *  定位和加载类(如要使用的类加载器)所需的信息不可用,并且该类可能根本不可加载。
      *  通过调用返回的注释上的相关方法尝试读取Class对象将导致MirroredTypeException,从中可以提取相应的TypeMirror。类似地,尝试读取Class[]-元素会导致MirroredTypesException
      *  注意:此方法与此相关接口中的其他方法不同。它对运行时反射信息(当前加载到VM中的注
      *  解类型的表示)进行操作,而不是对这些接口定义和使用的表示进行操作。因此,在调用由
      *  反射返回的注解对象上的方法时,对返回的注解对象上调用方法可以引发许多异常。此方法是
      *  调用方用于编写,已知的固定类型的注解类型上操作的。
      *  具体可以参考 JLS 9.6.1 Annotation Type Elements
     */
    <A extends Annotation> A getAnnotation(Class<A> annotationType);

    /**
     * 返回与该结构体关联的注解.
     * 如果没有的话,则返回长度为0的数组.
     * 注解的顺序是按照直接或者间接的声明的顺序,间接声明的注解就好像直接声明在C上一样.
     * 此方法与getAnnotation(Class)的区别在于,此方法检测其参数是否为可重复注解类型,如果是,则试图通过“looking through”来查找该类型的一个或多个容器注解。
     */
    <A extends Annotation> A[] getAnnotationsByType(Class<A> annotationType);
}

接下来我们就来看一下javax.lang.model.element包中的几个接口.

AnnotationMirror

代表一个注解.注解将值与注解类型的每个元素相关联。

注解之间的比较应该使用equals方法.无法保证任何特定的注解都是由一个对象来表示.

public interface AnnotationMirror {

    /**
     * 返回该注解的类型.其返回值DeclaredType在上一篇博客中有介绍
     */
    DeclaredType getAnnotationType();

    /**
     * 返回该注解的元素值.
     * 返回值为由对应的元素和它对应的值组成的map.
     * 只包括那些在注解中显式设置值的元素,而不包括那些隐式的默认值的元素。map中的顺序与注释的源中出现的值的顺序相匹配。
     * 注意如果是一个标记注解,则会返回空map.
     * 如果想要填充默认值的元素,使用Elements.getElementValuesWithDefaults()方法.
     */
    Map<? extends ExecutableElement, ? extends AnnotationValue> getElementValues();
}

AnnotationValue

代表注解元素的类型。其类型为:

  • 原始类型对应的包装类
  • String
  • TypeMirror
  • VariableElement(代表枚举)
  • AnnotationMirror
  • List
public interface AnnotationValue {

    /**
     * 返回该注解元素对应的值
     */
    Object getValue();

    /**
     * 返回该注解元素对应的值所对应的字符串形式
     */
    String toString();

    /**
     * 访问者模式
     * <R>-->该方法的返回值类型.
     * <P>-->额外添加的参数的类型
     * 参数P --> 额外添加的参数
     */
    <R, P> R accept(AnnotationValueVisitor<R, P> v, P p);
}

AnnotationValueVisitor

注释类型元素的值的访问者,使用访问者设计模式的变体。与标准访问者基于类型层次结构中成员的具体类型进行分派不同,该访问者基于所存储的数据类型进行分派;存储时没有子类之间的区别,如boolean与int.实现此接口的类用于操作在编译时未知该类型的值.如果访问者传递给了元素值的accept 方法,则所对应的visitXYZ 方法会被调用.

如果附加参数p为空,实现此接口的类可以抛出NullPointerException,也可以不抛出NullPointerException;有关详细信息,请参阅实现类的文档。

警告:有可能将方法添加到该接口,以适应添加到Java编程语言未来版本的新的、目前未知的语言结构。因此,直接实现此接口的访问者类可能与平台的未来版本不兼容。为了避免这种源不兼容性,我们鼓励访问者实现扩展实现这个接口的适当的抽象访问者类。但是,API通常应该使用这个访问者接口作为参数、返回类型等的类型,而不是一个抽象类。

注意,如果将用于适应新语言构造的方法作为默认方法添加,则可以以与源兼容的方式添加它们。但是,默认方法只在Java SE 8和更高版本上可用,javax.lang.model.* 捆绑在Java SE 8中的包也需要在Java SE 7上运行。因此,在扩展javax.lang.model.* 以覆盖Java SE 8语言特性时不能使用默认方法。但是,默认方法可以用于javax.lang.model.* 包的后续修订,这些包只需要在Java SE 8和更高的平台版本上运行。

该接口是一个泛型接口.其泛型参数介绍如下:

R –> 该访问方法的返回值
P –> 该访问方法额外添加的参数

public interface AnnotationValueVisitor<R, P> {
    /**
     * 访问AnnotationValue
     */
    R visit(AnnotationValue av, P p);

    /**
     * 和v.visit(av, null)方法具有同样效果的方法
     */
    R visit(AnnotationValue av);


    R visitBoolean(boolean b, P p);


    R visitByte(byte b, P p);


    R visitChar(char c, P p);


    R visitDouble(double d, P p);


    R visitFloat(float f, P p);


    R visitInt(int i, P p);


    R visitLong(long i, P p);


    R visitShort(short s, P p);


    R visitString(String s, P p);


    R visitType(TypeMirror t, P p);


    R visitEnumConstant(VariableElement c, P p);


    R visitAnnotation(AnnotationMirror a, P p);


    R visitArray(List<? extends AnnotationValue> vals, P p);

    /**
     * 访问注解值是一个未知类型的方法.
     * 这可以在语言的进化和新的类型可以存储在一个注解时出现这种情况。
     */
    R visitUnknown(AnnotationValue av, P p);
}

Element

该接口继承自javax.lang.model.AnnotatedConstruct.该接口代表java程序中的元素,比如包,类,或者方法.每个元素表示静态、语言级别的结构(而不是虚拟机的运行时结构)。

Element见的比较应该使用equals(Object)方法,无法保证任何特定的元素都是用一个对象来表示的

要实现基于元素对象类的操作,要么使用ElementVisitor,要么使用getKind方法的结果。使用instanceof不一定是确定此建模层次结构中对象的有效类的可靠习惯用法,因为实现可以选择让单个对象实现多个Element子接口。

public interface Element extends javax.lang.model.AnnotatedConstruct {
    /**
     * 返回该元素定义的类型。
     * 泛型元素定义了一系列类型,而不仅仅是一个类型。如果这是一个泛型元素,则返回一个原型
     * 类型。这是元素在对应于它自己的正式类型参数的类型变量上的调用。例如,对于泛型类元素
     * C<N extends Number>,返回参数化类型C<N>。类型实用程序接口有更一般的方法来获取元
     * 素定义的所有类型的范围。 
     */
    TypeMirror asType();

    /**
     * 返回该元素的类型
     */
    ElementKind getKind();

    /**
     * 返回该元素的修饰符,包括注解.
     * 隐式修饰符也包含,比如接口方法中的public和static
     */
    Set<Modifier> getModifiers();

    /**
     * 返回该元素的简单名称.泛型类型的名称不包括对其正式类型参数的任何引用。
     * 举例,java.util.Set<E>的简单名称是Set.
     * 如果该元素代表的是未命名包,则返回一个空 Name.
     * 如果代表的是构造器,则返回<init>所对应的Name.如果代表的是静态代码块,则返回的是<clinit>
     * 如果代表的是匿名类或者是初始代码块,则返回一个空 Name.
     */
    Name getSimpleName();

    /**
     * 返回包围该元素的最内层的元素.
     * 如果这个元素的声明紧接在另一个元素的声明中,则返回另一个元素。
     * 如果这是顶级类型,则返回其包。
     * 如果这是一个包,则返回null。
     * 如果这是类型参数,则返回类型参数的泛型元素。
     * 如果这是一个方法或构造函数参数,则返回声明该参数的可执行元素。
     */
    Element getEnclosingElement();

    /**
     * 返回该元素所包含的元素.
     * 类或接口被认为包含了它直接声明的字段、方法、构造函数和成员类型.包直接包含了顶级类和接
     * 口,但不包含其子包。其他类型的元素目前不被认为包含任何元素;然而,随着这个API或编程语
     * 言的发展,这些元素可能会改变
     */
    List<? extends Element> getEnclosedElements();

    /**
     * 当给定的参数和当前类代表同一个元素时返回true,否则,返回false.
     * 注意,元素的标识涉及不能直接从元素的方法中访问的隐式状态,包括关于不相关类型的存在的
     * 状态。即使“同一个”元素正在被建模,由这些接口的不同实现创建的元素对象也不应该期望相
     * 等;这类似于通过不同的类加载器加载的同一个类文件的Class对象是不同的
     *
     */
    @Override
    boolean equals(Object obj);

    /**
     * 基于Object.hashCode
     */
    @Override
    int hashCode();


    /**
     * 获得直接声明在该元素上的注解
     * 如果要获得继承的注解,使用Elements#getAllAnnotationMirrors(Element)方法.
     */
    @Override
    List<? extends AnnotationMirror> getAnnotationMirrors();


    @Override
    <A extends Annotation> A getAnnotation(Class<A> annotationType);


    <R, P> R accept(ElementVisitor<R, P> v, P p);
}

ElementKind

关于元素类型的枚举

public enum ElementKind {

    /** 包 */
    PACKAGE,

    // 声明类型
    /** 枚举 */
    ENUM,

    CLASS,
    /** 注解类型 */
    ANNOTATION_TYPE,
    /** 接口 */
    INTERFACE,

    // 变量
    /** 一个枚举常量 */
    ENUM_CONSTANT,
    /**
     * 字段
     */
    FIELD,
    /** 方法或者构造器中的参数 */
    PARAMETER,
    /** 本地变量 */
    LOCAL_VARIABLE,
    /** try-catch中的catch语句的异常类型*/
    EXCEPTION_PARAMETER,

    // 可执行的类型
    /** 方法 */
    METHOD,
    /** 构造器 */
    CONSTRUCTOR,
    /** 静态初始块 */
    STATIC_INIT,
    /** 初始块 */
    INSTANCE_INIT,

    /** 类型参数 */
    TYPE_PARAMETER,

    /**
     * An implementation-reserved element.  This is not the element
     * you are looking for.
     */
    OTHER,

    /**
     * A resource variable.
     * @since 1.7
     */
    RESOURCE_VARIABLE;


    /**
     * 如果当前是CLASS或者是枚举则返回true
     */
    public boolean isClass() {
        return this == CLASS || this == ENUM;
    }

    /**
     * 如果当前是INTERFACE或者ANNOTATION_TYPE则返回true
     */
    public boolean isInterface() {
        return this == INTERFACE || this == ANNOTATION_TYPE;
    }

    /**
     * 如果当前是FIELD或者是ENUM_CONSTANT则返回true
     */
    public boolean isField() {
        return this == FIELD || this == ENUM_CONSTANT;
    }
}

ElementVisitor

Element的访问者接口.

public interface ElementVisitor<R, P> {

    R visit(Element e, P p);


    R visit(Element e);


    R visitPackage(PackageElement e, P p);


    R visitType(TypeElement e, P p);


    R visitVariable(VariableElement e, P p);


    R visitExecutable(ExecutableElement e, P p);


    R visitTypeParameter(TypeParameterElement e, P p);


    R visitUnknown(Element e, P p);
}

Element接口有一系列的子接口,如图:

2

接下来,我们就来看一下.

Parameterizable

代表该元素有类型参数的接口,继承自Element.

public interface Parameterizable extends Element {
    /**
      * 以声明顺序返回类型元素的形式类型参数
      */
    List<? extends TypeParameterElement> getTypeParameters();
}

ExecutableElement

代表一个类或者接口的方法,构造器,或者初始块(静态或者实例的),包括注解类型.是Parameterizable的子接口.

public interface ExecutableElement extends Element, Parameterizable {
    /**
     * 按声明顺序返回形式类型参数
     */
    List<? extends TypeParameterElement> getTypeParameters();

    /**
     * 返回该类的返回类型.如果当前不是方法或者该方法没有返回值,则返回由
     * NoType和TypeKind#VOID组成的TypeMirror
     */
    TypeMirror getReturnType();

    /**
     * 按照声明顺序返回该类所对应的形式参数
     */
    List<? extends VariableElement> getParameters();

    /**
     * 返回当前类型所对应的接收器类型,如果没有对应的接收器,则返回由javax.lang.model.type.NoType和javax.lang.model.type.TypeKind#NONE组成的TypeMirror
     * 如果当前是一个实例方法,构造器或者是一个内部类,则其接收器类型可以由javax.lang.model.element.Element.getEnclosingElement()方法获得.
     * 如果当前是一个静态方法,或者是非内部类的构造器,或者是初始块(静态的或者是实例的),则没有接收器类型
     * 
     */
    TypeMirror getReceiverType();

    /**
     * 如果当前所对应的方法或者构造器接受可变参数,则返回true
     */
    boolean isVarArgs();

    /**
     * 如果当前所对应的是一个默认方法,则返回true
     */
    boolean isDefault();

    /**
     * 返回当前所对应的方法或者是构造器所对应的异常列表
     */
    List<? extends TypeMirror> getThrownTypes();

    /**
     * 如果当前对应的是一个注解元素,则返回其默认值,如果不是,或者该注解元素没有对应的默认值,则返回null
     */
    AnnotationValue getDefaultValue();

    /**
     * 返回构造器,方法或者初始化块所对应的Name.对于构造器,返回<init>,对于静态代码块,返回<clinit>,对于匿名类或者实例代码块,返回空的Name
     */
    @Override
    Name getSimpleName();
}

QualifiedNameable

代表有限定名的元素的接口.

public interface QualifiedNameable extends Element {
    /**
     * 返回该元素所对应的限定名
     */
    Name getQualifiedName();
}

TypeElement

代表java程序中的类或者接口.提供访问该类型和其内部成员的一些方法.注意,枚举类型看做是类,注解类型看做是接口.

TypeElement表示类或接口元素,而DeclaredType表示类或接口类型,后者是前者的使用(或调用).区分是最明显的泛型类型,其中一个元素可以定义一个完整类型的家族。例如,元素java.util.Set对应于参数化类型java.util.Set\

public interface TypeElement extends Element, Parameterizable, QualifiedNameable {
    /**
     * 返回在该类或者接口中直接声明的字段,方法,构造器和成员类型.
     * 包括(隐式的)默认构造器和在枚举类型中隐式的values和valueOf方法.

     注意,作为该接口所需的一般要求和排序行为的特定实例,所包含的元素列表将以自然顺序返回,以作为关于该类型的信息的原始来源。例如,如果关于类型的信息源自源文件,则元素将以源代码顺序返回。(但是,在这种情况下,没有指定合成元素的排序,例如默认构造函数。)
     *
     */
    @Override
    List<? extends Element> getEnclosedElements();

    /**
     * 获得该类型的嵌套的类型
     */
    NestingKind getNestingKind();

    /**
     * 返回该类型的全限定名.更确切地说,它返回规范名称。对于没有标准名称的本地和匿名类,返
     * 回空名称。泛型类型的名称不包括对其正式类型参数的任何引用。例如,接口java.util.Set\<E\>
     * 的完全限定名是“java.util.Set”,嵌套类型使用“..”作为分隔符,
     * 如“java.util.Map.Entry”。
     */
    Name getQualifiedName();

    /**
     * 返回该类型的简单名称,对于匿名类,返回空name
     *
     */
    @Override
    Name getSimpleName();

    /**
     * 返回该类型对应的直接父类,如果该类是一个接口或者该类是Object,则返回由NoType和TypeKind#NONE组成的TypeMirror
     */
    TypeMirror getSuperclass();

    /**
     * 如果当前是类,则返回实现的接口,如果是接口,则返回继承的接口
     */
    List<? extends TypeMirror> getInterfaces();

    /**
      * 按照声明顺序返回该类型的泛型参数
     */
    List<? extends TypeParameterElement> getTypeParameters();

    /**
     * 返回包下的顶级类型,并返回在词法上直接包围的嵌套类型
     */
    @Override
    Element getEnclosingElement();
}

NestingKind

对应嵌套类型的枚举类,嵌套类型有四种:顶级元素,成员,本地和匿名类.嵌套类型是一种非标准术语,用于表示这种分类。请注意,可能会在java平台的未来版本中添加其他嵌套类型。

public enum NestingKind {
    /**
     * 顶级类型,没有被其他类型所包含
     */
    TOP_LEVEL,

    /**
     * 其他类型的一个成员类
     */
    MEMBER,

    /**
     * 在类型之外的结构中声明的命名类型(本地)
     */
    LOCAL,

    /**
     * 匿名类
     */
    ANONYMOUS;

    /**
     * 当前元素对应的是嵌套类型吗?嵌套类型元素是,不是顶层的任何元素。内部类型元素是任何非静态的嵌套类型元素
     */
    public boolean isNested() {
        return this != TOP_LEVEL;
    }
}

以下是一个实例:

 import java.lang.annotation.*;
 import static java.lang.annotation.RetentionPolicy.*;
 import javax.lang.model.element.*;
 import static javax.lang.model.element.NestingKind.*;

 @Nesting(TOP_LEVEL)
 public class NestingExamples {
     @Nesting(MEMBER)
     static class MemberClass1{}

     @Nesting(MEMBER)
     class MemberClass2{}

     public static void main(String... argv) {
         @Nesting(LOCAL)
         class LocalClass{};

         Class<?>[] classes = {
             NestingExamples.class,
             MemberClass1.class,
             MemberClass2.class,
             LocalClass.class
         };

         for(Class<?> clazz : classes) {
             System.out.format("%s is %s%n",
                               clazz.getName(),
                               clazz.getAnnotation(Nesting.class).value());
         }
     }
 }

 @Retention(RUNTIME)
 @interface Nesting {
     NestingKind value();
 }

PackageElement

代表包的接口.

public interface PackageElement extends Element, QualifiedNameable {

    /**
     * 返回这个包的全限定名称.这也就是包的规范名称.如果是当前对应的是未命名包,则返回一个空Name
     */
    Name getQualifiedName();

    /**
     * 返回这个包的简单名称.这也就是包的规范名称.如果是当前对应的是未命名包,则返回一个空Name
     */
    @Override
    Name getSimpleName();

    /**
     * 返回声明在本包下的顶级类和接口,对于子包中声明的类和接口,是不包含在返回值的
     */
    @Override
    List<? extends Element> getEnclosedElements();

    /**
     * 如果当前对应的是未命名的包,则返回true
     */
    boolean isUnnamed();

    /**
     * 如果本包没有被其他包所包含,则返回null
     */
    @Override
    Element getEnclosingElement();
}

TypeParameterElement

代表泛型类,接口,方法或者构造器的形式类型参数.一个类型参数就对应的一个类型变量.

public interface TypeParameterElement extends Element {

    /**
     * 返回由该类型参数参数化的泛型类、接口、方法或构造函数
     */
    Element getGenericElement();

    /**
     * 返回此类型参数的边界。这是用于声明此类型参数的extends子句所给出的类型。如果没有显式使用extends子句,则java.lang.Object被认为是唯一绑定的。
     */
    List<? extends TypeMirror> getBounds();

    /**
     * 返回此类型参数的泛型元素。
     */
    @Override
    Element getEnclosingElement();
}

VariableElement

代表一个字段,枚举常量,方法或者构造器的参数,本地变量,try-with-resource中的resource 变量,或者是异常参数.

public interface VariableElement extends Element {

    /**
     * 如果当前对应的是fianl修饰的字段,是在编译期初始化的常量,则返回对应的值,否则返回null.
     * 其常量值可能是原始类型或者是String,如果是原始类型,则返回对应的包装类。
     * 不是所有的finale字段都是常量值,如枚举的常量就不认为是编译期的常量。若要具有常量值,字段的类型必须是原始类型或字符串。
     */
    Object getConstantValue();

    /**
     * 返回该元素的简单名称.
     * 对于在同一方法或者构造器的参数类来说,其名字应该与其他的参数是不同的.
     * 如果在源文件的名称不可视,则实现可以合成符合上述不同性要求的名称。
     *
     */
    @Override
    Name getSimpleName();

    /**
     * 返回该元素正在包围的元素.
     * 对于方法或者构造器参数所包围的元素是其所对应的参数
     *
     */
    @Override
    Element getEnclosingElement();
}

UnknownElementException

当遇到未知类型的元素时会抛出该异常.如果语言进化并将新类型的元素添加到Element的层次结构中,则会发生这种情况。可以由Element访问者抛出,以指示访问者是为语言的先前版本创建的。

public class UnknownElementException extends UnknownEntityException {

    private static final long serialVersionUID = 269L;

    private transient Element element;
    private transient Object parameter;

    /**
     * 创建一个新的UnknownElementException.参数p可能会用来提供一些该未知元素出现的信息.举例,如ElementVisitor的visit方法可能会传递他们的额外参数
     */
    public UnknownElementException(Element e, Object p) {
        super("Unknown element: " + e);
        element = e;
        this.parameter = p;
    }


    public Element getUnknownElement() {
        return element;
    }


    public Object getArgument() {
        return parameter;
    }
}
  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值