问题
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,
TypeElementrepresents aclassorinterfaceprogram element. Provides access to information about the type and its members. Note that anenumtype is a kind of class and an annotation type is a kind ofinterface.
DeclaredTyperepresents a declared type, either aclasstype or aninterfacetype. This includes parameterized types such asjava.util.Set<String>as well as raw types.
Difference between the two:
While a
TypeElementrepresents aclassorinterfaceelement, aDeclaredTyperepresents aclassorinterfacetype, 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