了解' TypeElement'和' DeclaredType' java中的接口

时间:2015-07-06 12:18:04

标签: java interface annotations java-8

这两个界面的一个用法是编写注释处理器。

作为一个java初学者,我找到了这两个包添加的间接级别: javax.lang.model.element& javax.lang.model.type提供有关java interface和java class令人困惑的元数据。

enter image description here .........

enter image description here

java doc评论说,

  

TypeElement代表classinterface计划元素。提供对类型及其成员的信息的访问。请注意enum   type是一种类,注释类型是interface

     

DeclaredType表示声明的类型,class类型或interface类型。这包括参数化类型,例如java.util.Set<String>以及原始类型。

两者之间的区别:

  

虽然TypeElement代表classinterface 元素,但DeclaredType代表class或{{1} } type ,后者是前者的使用(或调用)。

如何区分行话元素类型?例如:interface 元素class 类型的不同之处是什么?请帮我举个例子。

3 个答案:

答案 0 :(得分:3)

元素是用于组成软件的部分,即ExecutableElement,顾名思义,它包含可执行代码,VariableElement描述了存储类型和TypeElement将它们组合在一起。它是Java编程语言(作为面向对象语言)的一种特殊属性,它没有顶级函数,也没有TypeElement的全局变量,在这些函数中定义了它们。

换句话说,如果您编写Java程序,您将始终至少有一个包含至少一个类型声明的.java源文件。 TypeElement可能包含至少一个ExecutableElement来构成有用的软件。 TypeElement可能包含多个ExecutableElement s,VariableElement和嵌套TypeElement。这是你的程序的结构

类型是您在声明成员或局部变量时使用的东西,也是在声明超类或接口时使用的。但是,让我们关注变量,以便更好地理解:

变量可以具有原始类型,该原始类型是编程语言固有的,它也可以具有隐含存在的类型,例如,当存在类型X时,您也可以在变量声明中使用数组类型X[],但只有声明的类型是必须具有相应{{ 1}},代表某些东西,开发人员已经编写过(或者是由工具生成的)。泛型还允许您撰写类型,例如声明类型为TypeElement的变量,而Set<? extends Number>Set声明的类型,它们具有相应的程序元素......

答案 1 :(得分:2)

  

如何区分行话元素与类型?例如:类元素与类类型有何不同?请帮我举个例子。

您可以将DeclaredType(类型)视为类的泛型类型(例如List<String>);与TypeElement(元素)相比,它基本上忽略了泛型类型(例如List)。

您可以从元素开始,并构建泛型类型:

// Utility elements that come with javax.annotation.processing
Elements elements = processingEnv.getElementUtils();
Types types = processingEnv.getTypeUtils();

// These are elements, they never have generic types associated
TypeElement listElement = elements.getTypeElement(List.class.getName());
TypeElement strElement  = elements.getTypeElement(String.class.getName());

// Build a Type: List<String>
DeclaredType listStrType = types.getDeclaredType(
                               listElement, 
                               strElement.asType());

// Build a Type: List<List<String>>
DeclaredType listlistStrType = types.getDeclaredType(
                               listElement,
                               listElement.asType(),
                               listStrType);

答案 2 :(得分:0)

首先,我必须承认我不是Java Guru,但发现你的问题很有趣并且花了一些时间来学习它。这是我发现的。

在我看来,整个概念与泛型有着极大的联系。如本答案中所述:https://stackoverflow.com/a/2127320/4250114

TypeElement是一种静态定义的类型,例如List<E>List<? extends SomeType>。而DeclaredType是具体的List<String>

关于这个概念的一些额外见解给了我Types#getDeclaredType方法的javadoc:

  

返回与type元素对应的类型   实际类型参数。   给定{@code Set}的类型元素和类型镜像   对于{@code String},   例如,此方法可用于获取   参数化类型{@code Set}。

正如引用问题(https://stackoverflow.com/a/2127266/4250114)中的另一个答案中所提到的,如果你想学习更多关于Gilad Bracha和David Ungar的论文应该是一个好地方(至少我会去;))。

当然你也可以自己试验。例如,我用调试器编写了这样的处理器:

@SupportedAnnotationTypes({"annotationProcessor.MyAnnotation"})
@SupportedSourceVersion(SourceVersion.RELEASE_8)
public class AnnotationProcessor extends AbstractProcessor {

    @Override
    public synchronized void init(ProcessingEnvironment processingEnv) {
        super.init(processingEnv);
        final Map.Entry<TypeElement, DeclaredType> collection = getType("java.util.Collection");
        final Map.Entry<TypeElement, DeclaredType> string = getType("java.util.String");
    }

    @Override
    public boolean process(Set<? extends TypeElement> annotations,
                           RoundEnvironment roundEnv) {
        return false;
    }


    private Types typeUtils() {
        return processingEnv.getTypeUtils();
    }

    private Map.Entry<TypeElement, DeclaredType> getType(String className) {
        TypeElement typeElement = processingEnv.getElementUtils().getTypeElement(className);
        DeclaredType declaredType = typeUtils().getDeclaredType(typeElement);
        return new HashMap.SimpleEntry<>(typeElement, declaredType);
    }
}

希望它有所帮助...