Understanding 'TypeElement' and 'DeclaredType' interface in java

坚强是说给别人听的谎言 提交于 2020-01-01 02:52:12

问题


One usage of these two interface, is to write annotation processor.

As a java beginner, I find the level of indirection that is added by these two packages: javax.lang.model.element & javax.lang.model.type to provide metadata about java interface and java class confusing.

.........

java doc comments say,

TypeElement represents a class or interface program element. Provides access to information about the type and its members. Note that an enum type is a kind of class and an annotation type is a kind of interface.

DeclaredType represents a declared type, either a class type or an interface type. This includes parameterized types such as java.util.Set<String> as well as raw types.

Difference between the two:

While a TypeElement represents a class or interface element, a DeclaredType represents a class or interface type, the latter being a use (or invocation) of the former.

How do I differentiate the jargon element from type? For example: How is class element different from class type? Please help me with an example.


回答1:


The elements are the parts that you use to compose a software, i.e. ExecutableElements which, as the name suggests, contain executable code, VariableElements which describe a kind of storage and TypeElements which hold these together. It’s a special property of the Java programming language (as an object oriented language) that there are no top-level functions nor global variables without a TypeElement, in which they are defined.

In other words, if you write a Java program, you will always have at least one .java source file containing at least one type declaration. That TypeElement will likely contain at least one ExecutableElement to make up a useful software. The TypeElement may contain multiple ExecutableElements, VariableElements and nested TypeElements. That’s the structure of your program.


A type is something which you use whenever you declare a member or local variable, but also when declaring a super class or -interface. But let’s focus on variables, for a better understanding:

A variable can have a primitive type, which is intrinsic to the programming language, it can also have a type whose existence is implied, e.g. when there is a type X, you can also use the array type X[] in a variable declaration, but only the declared type is a type which must have a corresponding TypeElement, representing something, a developer has written (or has been generated by a tool). Generics also allow you to compose types, e.g. declare a variable of type Set<? extends Number> whereas Set and Number are declared types which have corresponding program elements…




回答2:


How do I differentiate the jargon element from type? For example: How is class element different from class type? Please help me with an example.

You can think of the DeclaredType (type) as the generic type of a class (e.g. List<String>); compared to TypeElement (element) which essentially ignores the generic type (e.g. List).


You can start with elements, and build up generic types:

// 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);



回答3:


So first of all I must admit I am no Java Guru, but found your question interesting and spent some time learning about it. Here's what I found out.

In my opinion the whole concept is hugely connected with generics. As mentioned in this answer: https://stackoverflow.com/a/2127320/4250114

TypeElement is a statically defined type e.g List<E>, List<? extends SomeType>. Whereas DeclaredType is a concrete one like List<String>.

Some extra insight about the concept gave me the javadoc of Types#getDeclaredType method:

Returns the type corresponding to a type element and actual type arguments. Given the type element for {@code Set} and the type mirror for {@code String}, for example, this method may be used to get the parameterized type {@code Set}.

As mentioned in another answer in the cited question (https://stackoverflow.com/a/2127266/4250114) if you want to learn some more the paper of Gilad Bracha and David Ungar should be a good place(at least I am going to ;) ).

Of course you could also experiment on your own. E.g I have written such Processor that I was examining with debugger:

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

Hope it helped...



来源:https://stackoverflow.com/questions/31245638/understanding-typeelement-and-declaredtype-interface-in-java

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!