类型isAssignable和isSubtype误解

Pat*_*ick 11 java annotation-processing

在使用Java 6 API编写注释处理器时,我遇到了以特定方式处理所有地图的需求,但我显然误解了API的目的或如何调用它.这是让我不开心的代码:

import javax.lang.model.element.Element;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.Elements;
import javax.lang.model.util.Types;
import javax.annotation.processing.ProcessingEnvironment;
...

public String doThing(Element el, ProcessingEnvironment processingEnv) {
    // Utilities from the ProcessingEnvironment
    Types typeUtils = processingEnv.getTypeUtils();
    Elements elementUtils = processingEnv.getElementUtils();

    // The type of the element I'm handling
    TypeMirror elType = el.asType();

    // Compare the element's type to Map
    TypeMirror mapType = elementUtils.getTypeElement("java.util.Map").asType();

    System.out.println(elType + " > " + mapType + " = " + typeUtils.isSubtype(elType, mapType));
    System.out.println(mapType + " > " + elType + " = " + typeUtils.isSubtype(mapType, elType));
    System.out.println(elType + " > " + mapType + " = " + typeUtils.isAssignable(elType, mapType));
    System.out.println(mapType + " > " + elType + " = " + typeUtils.isAssignable(mapType, elType));

    // Compare the element's type to HashMap
    TypeMirror hashmapType = elementUtils.getTypeElement("java.util.HashMap").asType();

    System.out.println(elType + " > " + hashmapType + " = " + typeUtils.isSubtype(elType, hashmapType));
    System.out.println(hashmapType + " > " + elType + " = " + typeUtils.isSubtype(hashmapType, elType));
    System.out.println(elType + " > " + hashmapType + " = " + typeUtils.isAssignable(elType, hashmapType));
    System.out.println(hashmapType + " > " + elType + " = " + typeUtils.isAssignable(hashmapType, elType));


    // Compare the element's type to Object
    TypeMirror objectType = elementUtils.getTypeElement("java.lang.Object").asType();

    System.out.println(elType + " > " + objectType + " = " + typeUtils.isSubtype(elType, objectType));
    System.out.println(objectType + " > " + elType + " = " + typeUtils.isSubtype(objectType, elType));
    System.out.println(elType + " > " + objectType + " = " + typeUtils.isAssignable(elType, objectType));
    System.out.println(objectType + " > " + elType + " = " + typeUtils.isAssignable(objectType, elType));
}
Run Code Online (Sandbox Code Playgroud)

鉴于此,这是它的输出:

java.util.HashMap<K,V> > java.util.Map<K,V> = false
java.util.Map<K,V> > java.util.HashMap<K,V> = false
java.util.HashMap<K,V> > java.util.Map<K,V> = false
java.util.Map<K,V> > java.util.HashMap<K,V> = false

java.util.HashMap<K,V> > java.util.HashMap<K,V> = true
java.util.HashMap<K,V> > java.util.HashMap<K,V> = true
java.util.HashMap<K,V> > java.util.HashMap<K,V> = true
java.util.HashMap<K,V> > java.util.HashMap<K,V> = true

java.util.HashMap<K,V> > java.lang.Object = true
java.lang.Object > java.util.HashMap<K,V> = false
java.util.HashMap<K,V> > java.lang.Object = true
java.lang.Object > java.util.HashMap<K,V> = false
Run Code Online (Sandbox Code Playgroud)

这对我来说非常有意义,除了我希望HashMap元素可以分配给Map的第一个块,我希望HashMap是Map的子类型.

我在这里错过了什么?

Ian*_*rts 9

我怀疑这是因为类型变量.HashMap<String, String>可以赋值Map<String, String>但没有类型变量的具体实例化,你无法确定任意值HashMap<A,B>是否可赋值Map<X,Y>.

如果使用通配符实例化变量,那么您应该得到预期的结果

DeclaredType wildcardMap = typeUtils.getDeclaredType(
    elementUtils.getTypeElement("java.util.Map"),
    typeUtils.getWildcardType(null, null),
    typeUtils.getWildcardType(null, null));
Run Code Online (Sandbox Code Playgroud)

这将为您提供类型镜像Map<?,?>,所有HashMap实例化都可以分配给它.

  • 整个方法及其@Patrick的实现都太复杂了。只需使用types.isAssignable(type,types.erasure(baseGenerifiedType))(例如,检查类型是否可分配给原始的HashMap而不是HashMap &lt;?,?&gt;) (2认同)