Types isAssignable and isSubtype misunderstanding
annotation-processing, java
Solution
I suspect it's because of the type variables. `HashMap<String, String>` is assignable to `Map<String, String>` but without the concrete instantiation of the type variables you can't be sure that an arbitrary `HashMap<A,B>` is assignable to `Map<X,Y>`.
If you instantiate the variables with wildcards then you should get the result you expect
DeclaredType wildcardMap = typeUtils.getDeclaredType(
elementUtils.getTypeElement("java.util.Map"),
typeUtils.getWildcardType(null, null),
typeUtils.getWildcardType(null, null));
This will give you the type mirror for `Map<?,?>`, which all `HashMap` instantiations are assignable to.
Problem
In writing an Annotation Processor using the Java 6 API, I came across a need to handle all Maps in a particular fashion, but I'm clearly misunderstanding what the API is intended to do or how to invoke it. Here's the code that's making me unhappy: ``` 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)); } ``` Given that, here's the output of it: ``` 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 ``` This makes perfect sense to me except for the first block where I'd expect a HashMap element to be assignable to Map, and I'd expect HashMap to be a subtype of Map. What am I missing here?