问题
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 aclass
orinterface
program element. Provides access to information about the type and its members. Note that anenum
type is a kind of class and an annotation type is a kind ofinterface
.
DeclaredType
represents a declared type, either aclass
type or aninterface
type. This includes parameterized types such asjava.util.Set<String>
as well as raw types.
Difference between the two:
While a
TypeElement
represents aclass
orinterface
element, aDeclaredType
represents aclass
orinterface
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. ExecutableElement
s which, as the name suggests, contain executable code, VariableElement
s which describe a kind of storage and TypeElement
s 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 ExecutableElement
s, VariableElement
s and nested TypeElement
s. 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