2009-08-18 14 views
16

जावा अक्सर तर्कों के आधार पर जेनरिक का अनुमान लगा सकता है (और यहां तक ​​कि वापसी प्रकार पर, उदाहरण के लिए सी #)।बदले में वाइल्डकार्ड जेनेरिक

बिंदु में मामला:

Pair<String, String> pair = Pair.of("Hello", "World"); 

विधि of सिर्फ इस तरह दिखता है:

मैं एक सामान्य वर्ग Pair<T1, T2> जो सिर्फ मूल्यों की एक जोड़ी संग्रहीत करता है और निम्नलिखित तरीके से इस्तेमाल किया जा सकता है
public static <T1, T2> Pair<T1, T2> of(T1 first, T2 second) { 
    return new Pair<T1, T2>(first, second); 
} 

बहुत अच्छा। बहरहाल, यह नहीं रह गया है निम्नलिखित यूज-केस, जो वाइल्डकार्ड की आवश्यकता है के लिए काम करता है: (। सूचना स्पष्ट डाली List.class सही प्रकार बनाने के लिए)

Pair<Class<?>, String> pair = Pair.of((Class<?>) List.class, "hello"); 

कोड प्रदान की निम्न त्रुटि (के साथ विफल ग्रहण से):

प्रकार बेमेल: TestClass.Pair<Class<capture#1-of ?>,String> से परिवर्तित नहीं कर सकते TestClass.Pair<Class<?>,String>

को

हालांकि, स्पष्ट रूप से बुला निर्माता अभी भी काम करता है के रूप में उम्मीद:

Pair<Class<?>, String> pair = 
    new Pair<Class<?>, String>((Class<?>) List.class, "hello"); 

कोई इस व्यवहार की व्याख्या कर सकते हैं? क्या यह डिजाइन द्वारा है? क्या यह चाहता था? क्या मैं कुछ गलत कर रहा हूं या क्या मैं कंपाइलर में डिज़ाइन/बग में एक दोष पर ठोकर खा रहा हूं?

जंगली अनुमान: किसी भी तरह प्रकार एक Class<List> बनाने, और इस तरह रूपांतरण (Pair<Class<?>, String> से Pair<Class<List>, String> करने के लिए) में नाकाम रहने, सूचित करते हैं कि वाइल्डकार्ड मक्खी पर संकलक द्वारा में भर जाता है लगता है? "1-के # कब्जा" । क्या यह सही है? क्या इस के आसपास काम करने का कोई तरीका है?

public final class Pair<T1, T2> { 
    public final T1 first; 
    public final T2 second; 

    public Pair(T1 first, T2 second) { 
     this.first = first; 
     this.second = second; 
    } 

    public static <T1, T2> Pair<T1, T2> of(T1 first, T2 second) { 
     return new Pair<T1, T2>(first, second); 
    } 
} 
+0

ऐसा लगता है कि कनवर्टर "के" के हस्ताक्षर को देखता है क्योंकि यह एक जोड़ी देता है बढ़ाता है,? वर्ग > प्रकार बढ़ाता है। अंतिम कक्षाओं के लिए यह विस्तारित भाग को कम करने के लिए पर्याप्त स्मार्ट लगता है, यही कारण है कि यह स्ट्रिंग पर शिकायत नहीं करता है। – Zed

+0

हम्म, दिलचस्प। मुझे यहां जोड़ने के लिए धन्यवाद। – jjnguy

+0

अब यह जावा 8 में काम करता है। इनफ्रेंस के लिए लक्ष्य प्रकार से भी परामर्श लिया जाता है। – ZhongYu

उत्तर

13

कारण निर्माता काम करता है कि आप स्पष्ट रूप से प्रकार पैरामीटर निर्दिष्ट कर रहे है:


पूर्णता 'के लिए, यहाँ Pair वर्ग का एक सरलीकृत संस्करण है।

Pair<Class<?>, String> pair = Pair.<Class<?>, String>of(List.class, "hello"); 

बेशक, पूरी कारण आप पहली जगह में एक स्थिर विधि शायद सिर्फ प्रकार निष्कर्ष (जिस पर कंस्ट्रक्टर्स साथ काम नहीं करता प्राप्त करने के लिए है: स्थिर विधि भी अगर आप ऐसा काम करेंगे सब)।

यहां समस्या (जैसा कि आपने सुझाव दिया है) यह है कि संकलक capture conversion कर रहा है। मेरा मानना ​​है कि इस [§15.12.2.6 of the JLS] का एक परिणाम के रूप में है:

  • चयनित पद्धति का परिणाम प्रकार इस प्रकार निर्धारित किया जाता है:
    • विधि लागू की जा रही शून्य, की वापसी प्रकार के साथ घोषित किया जाता है तो तो परिणाम शून्य है।
    • अन्यथा, यदि विधि लागू होने के लिए अनचेक रूपांतरण आवश्यक था तो परिणाम प्रकार विधि का घोषित रिटर्न प्रकार का मिटा (§4.6) है।
    • अन्यथा, यदि विधि लागू की जा रही 1in के लिए, सामान्य है तो, फाई की औपचारिक प्रकार पैरामीटर विधि हो, ऐ वास्तविक प्रकार तर्क विधि मंगलाचरण लिए लगाए गए अनुमान हो, और आर रहने दो घोषित की विधि का वापसी प्रकार घोषित किया गया। परिणाम प्रकार प्राप्त होता है कैप्चर रूपांतरण (§5.1.10) आर [एफ 1: = ए 1, ..., एफएन: = ए] पर लागू करके।
    • अन्यथा, परिणाम घोषणा विधि रूपांतरण (§5.1.10) को विधि घोषणा में दिए गए पर लागू करके प्राप्त किया जाता है।

तुम सच में अनुमान चाहते हैं, एक संभावित समाधान, इस तरह कुछ करने के लिए है:

Pair<? extends Class<?>, String> pair = Pair.of(List.class, "hello"); 

चर pair एक व्यापक प्रकार होगा, और यह थोड़ा मतलब है चर के प्रकार के नाम में अधिक टाइपिंग, लेकिन कम से कम आपको विधि कॉल में डालने की आवश्यकता नहीं है।

+0

बहुत बहुत धन्यवाद। मैं अभी भी इस पर विचार कर रहा हूं कि क्या कामकाज कोर को और भी भ्रमित नहीं करता है। इस पल के लिए, मैं इसे छोड़ दूंगा। –

संबंधित मुद्दे