【问题标题】:Understanding 'TypeElement' and 'DeclaredType' interface in java理解java中的'TypeElement'和'DeclaredType'接口
【发布时间】:2015-09-23 14:06:02
【问题描述】:

这两个接口的一个用法,就是写注解处理器。

作为一个 java 初学者,我发现这两个包添加的间接级别: javax.lang.model.element & javax.lang.model.type 提供有关 java interface 和 java class 混淆的元数据。

.........

java doc cmets 说,

TypeElement 表示classinterface 程序元素。提供对有关类型及其成员的信息的访问。请注意,enum type 是一种类,注解类型是一种interface

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

两者的区别:

TypeElement 表示classinterface元素DeclaredType 表示classinterface 类型,后者是前者的使用(或调用)。

如何区分行话 elementtype?例如:classelementclasstype 有何不同?请帮我举个例子。

【问题讨论】:

    标签: java interface annotations java-8


    【解决方案1】:

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

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


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

    变量可以具有编程语言固有的原始类型,也可以具有隐含存在的类型,例如当有X类型时,也可以在变量声明中使用数组类型X[],但只有声明类型是必须有对应TypeElement的类型,代表什么,开发人员编写(或已由工具生成)。泛型还允许您组合类型,例如声明一个Set<? extends Number> 类型的变量,而SetNumber声明的类型,它们具有相应的程序元素……

    【讨论】:

    • 对于你的观点:“声明的类型是一个必须有一个对应的TypeElement,代表某种东西的类型”,如果我们拿这个example,你如何区分class X的TypeElement类型和DeclaredType类型?
    • 我不明白你的问题。为什么我要尝试区分对同一事物有不同看法的两件事?重要的一点是 Type 角色可以由 not 元素的实体来完成,即intvoid,以及 Element 角色可以通过非声明类型的事物来实现,例如变量ijargs 或方法m1m2main 在您的示例中。您似乎过于关注这两个概念的交集而不是差异。然后你要求找出交叉口内的差异……
    • 好的。所以,你的意思是,m1m2main 具有ExecutableElement 类型的角色。 ijargs 具有 VariableElement 类型角色。 X 具有 TypeElement 角色。 intvoid 具有 PrimitiveType 角色。我对么?在我的示例中,DeclaredType 类型角色是什么?
    【解决方案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);
    

    【讨论】:

      【解决方案3】:

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

      在我看来,整个概念与泛型密切相关。正如这个答案中提到的:https://stackoverflow.com/a/2127320/4250114

      TypeElement 是静态定义的类型,例如 List&lt;E&gt;List&lt;? extends SomeType&gt;。而DeclaredType 是一个具体的List&lt;String&gt;

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

      返回对应于类型元素的类型和 实际类型参数。 给定 {@code Set} 的类型元素和类型镜像 对于 {@code 字符串}, 例如,此方法可用于获取 参数化类型 {@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);
          }
      }
      

      希望对您有所帮助...

      【讨论】:

      • 请看一下新图,根据这个新图,TypeElementDeclaredType 有什么区别?
      • 同理。如您所见,由于“?”,TypElement public @interface CompanionClass { Class&lt;?&gt; friend() } 代表了整个类型的“家族”。声明的类型之一是public @interface CompanionClass{Class&lt;Bar&gt; friend()}。至于AnnotationValue,它是class Bar,所以在这种情况下TypeElement = DeclaredType,因为没有占位符。
      • 抱歉,您如何区分example 中的TypeElementDeclaredType class X
      • 对于此类,它们产生相同的构造 TypElementDeclaredType 都只是 class X,但它们代表不同的逻辑层。
      • 不同层次的逻辑?我没有得到你
      猜你喜欢
      • 1970-01-01
      • 2023-03-19
      • 2014-11-21
      • 1970-01-01
      • 2014-08-21
      • 1970-01-01
      • 1970-01-01
      • 2018-07-29
      • 1970-01-01
      相关资源
      最近更新 更多