2012-10-05 16 views
11

जावा 6 एपीआई का उपयोग करके एक एनोटेशन प्रोसेसर लिखने में, मुझे किसी विशेष फैशन में सभी मैप्स को संभालने की ज़रूरत आई, लेकिन मैं स्पष्ट रूप से गलत समझ रहा हूं कि एपीआई क्या करना है या कैसे आना है यह।प्रकार isssignable है और isSubtype गलतफहमी

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)); 
} 

यह देखते हुए कि, यहाँ यह के उत्पादन में बताया गया है::

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 

यह पहला ब्लॉक के अलावा मेरे लिए एकदम सही समझ में आता है जहां मैं एक उम्मीद थी यहाँ कोड है कि मुझे दुखी करने है हैश मैप तत्व को मानचित्र के लिए असाइन करने योग्य है, और मैं उम्मीद करता हूं कि हैश मैप मानचित्र का उप-प्रकार बन जाएगा।

मुझे यहां क्या याद आ रही है?

उत्तर

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)); 

यह Map<?,?> है, जो सभी HashMap instantiations को आबंटित कर रहे हैं के लिए आप प्रकार दर्पण दे देंगे।

+0

तुम्हें पता है आह्वान, मैंने सोचा था कि, और मैं मिलान कि प्रकार के मेल खाते हैं सामान्य पत्र के बाद से सोचा, लेकिन मैं नहीं लगता है। धन्यवाद! – Patrick

+1

यह संपूर्ण दृष्टिकोण और @ पैट्रिक का कार्यान्वयन बहुत जटिल है। बस 'type.isAssignable (type, type.erasure (baseGenerifiedType)) का उपयोग करें' (उदाहरण के लिए जांचें कि 'हैश मैप ' के बजाय कच्चे 'हैश मैप' को टाइप करने योग्य है या नहीं) – user1643723

2

अद्यतन (मार्च 2016): @ user1643723 द्वारा एक टिप्पणी के आधार पर, वहाँ एक types.erasure(TypeMirror) पुस्तकालय समारोह होने के लिए है कि मैं पर Ian's Answer आधार में 2012


की जानकारी नहीं थी प्रतीत होता है, मैं मैं अब प्रश्नों में मानचित्र के लिए वर्णित मूल प्रकारों से मेल खाने के लिए निम्न विधि का उपयोग कर रहा हूं।

TypeElement COLLECTION = elementUtils.getTypeElement("java.util.Collection"); 
TypeElement MAP = elementUtils.getTypeElement("java.util.Map"); 
TypeElement VOID = elementUtils.getTypeElement("java.lang.Void"); 
WildcardType WILDCARD_TYPE_NULL = typeUtils.getWildcardType(null, null); 
Map<String,DeclaredType> cachedParentTypes = new HashMap<String, DeclaredType>(); 

... 

public static boolean isA(TypeMirror type, TypeElement typeElement) { 

    // Have we used this type before? 
    DeclaredType parentType = cachedParentTypes.get(typeElement.getQualifiedName().toString()); 
    if (parentType == null) { 
     // How many generic type parameters does this typeElement require? 
     int genericsCount = typeElement.getTypeParameters().size(); 

     // Fill the right number of types with nulls 
     TypeMirror[] types = new TypeMirror[genericsCount]; 
     for (int i = 0; i < genericsCount; i++) { 
      types[i] = WILDCARD_TYPE_NULL; 
     } 

     // Locate the correct DeclaredType to match with the type 
     parentType = typeUtils.getDeclaredType(typeElement, types); 

     // Remember this DeclaredType 
     cachedParentTypes.put(typeElement.getQualifiedName().toString(), parentType); 
    } 

    // Is the given type able to be assigned as the typeElement? 
    return typeUtils.isAssignable(type, parentType); 
} 

जो मैं की तरह

if (isA(elType, VOID)) { 
    isVoid = true; 
} else if (isA(elType, COLLECTION) || elType.getKind() == TypeKind.ARRAY) { 
    isCollectionOrArray = true; 
} else if (isA(elType, MAP)){ 
    isMap = true; 
} 
संबंधित मुद्दे