Understanding 'TypeElement' and 'DeclaredType' interface in java
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.
The elements are the parts that you use to compose a software, ie 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, eg 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, eg declare a variable of type Set<? extends Number>
Set<? extends Number>
whereas Set
and Number
are declared types which have corresponding program elements…
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 (eg List<String>
); compared to TypeElement
(element) which essentially ignores the generic type (eg 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);
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 eg List<E>
, List<? extends SomeType>
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. Eg 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...
链接地址: http://www.djcxy.com/p/86442.html