मैंने अभी इसका परीक्षण किया है, असाइनमेंट स्वयं संकलित करता है। क्या परिवर्तन यह है कि आप वास्तव में predicate.test()
पर कॉल कर सकते हैं।
चलो एक कदम पीछे ले जाएं और स्पष्टीकरण के लिए प्लेसहोल्डर GenericClass<T>
का उपयोग करें। तर्क तर्क के लिए, Foo
Bar
और Bar
विस्तारित करता है Baz
।
का विस्तार: जब आप एक GenericClass<? extends Bar>
घोषित, आप कह रहे हैं "मैं क्या इसके जेनेरिक प्रकार तर्क वास्तव में नहीं पता है, लेकिन यह Bar
का एक उपवर्ग है।" वास्तविक उदाहरण में हमेशा एक गैर-वाइल्डकार्ड प्रकार तर्क होगा, लेकिन कोड के इस हिस्से में आप नहीं जानते कि इसका मूल्य क्या है। अब विचार करें कि विधि आमंत्रण के लिए इसका क्या अर्थ है।
आप जानते हैं कि आपको वास्तव में क्या मिला है या तो GenericClass<Foo>
या GenericClass<Bar>
है। T
लौटने वाली विधि पर विचार करें। पूर्व मामले में, इसका रिटर्न प्रकार Foo
है। बाद में, Bar
। किसी भी तरह से, यह Bar
का उप प्रकार है और Bar
चर को असाइन करने के लिए सुरक्षित है।
एक ऐसी विधि पर विचार करें जिसमें T
पैरामीटर है। यदि यह GenericClass<Foo>
है, तो इसे Bar
पास करना एक त्रुटि है - Bar
Foo
का उप प्रकार नहीं है।
तो, ऊपरी बाउंड के साथ आप जेनेरिक रिटर्न मानों का उपयोग कर सकते हैं, लेकिन जेनेरिक विधि पैरामीटर नहीं।
सुपर: जब आप एक GenericClass<? super Bar>
घोषित, आप कह रहे हैं "मैं क्या इसके जेनेरिक प्रकार तर्क वास्तव में नहीं पता है, लेकिन यह Bar
की एक सुपर क्लास है।" अब विचार करें कि विधि आमंत्रण के लिए इसका क्या अर्थ है।
आप जानते हैं कि आपको वास्तव में क्या मिला है या तो GenericClass<Bar>
या GenericClass<Baz>
है। T
लौटने वाली विधि पर विचार करें। पूर्व मामले में, यह Bar
देता है। बाद में, Baz
। यदि यह Baz
देता है, तो उस मान को Bar
चर पर असाइन करना एक त्रुटि है। आप नहीं जानते कि यह कौन सा है, इसलिए आप सुरक्षित रूप से यहां कुछ भी नहीं मान सकते हैं।
एक ऐसी विधि पर विचार करें जिसमें T
पैरामीटर है। यदि यह GenericClass<Bar>
है, तो इसे Bar
पास करना कानूनी है। यदि यह GenericClass<Baz>
है, तो इसे Bar
पास करना अभी भी कानूनी है क्योंकि Bar
Baz
का उप प्रकार है।
तो, निचले बाउंड के साथ आप जेनेरिक विधि पैरामीटर का उपयोग कर सकते हैं, लेकिन सामान्य वापसी मान नहीं।
सारांश में: <? extends T>
का अर्थ है कि आप जेनेरिक रिटर्न वैल्यू का उपयोग कर सकते हैं लेकिन पैरामीटर नहीं। <? super T>
का मतलब है कि आप जेनेरिक पैरामीटर का उपयोग कर सकते हैं लेकिन मान वापस नहीं कर सकते हैं। Predicate.test()
में एक सामान्य पैरामीटर है, इसलिए आपको super
की आवश्यकता है।
विचार करने की एक और बात: वाइल्डकार्ड द्वारा दी गई सीमाएं वस्तु के वास्तविक प्रकार के तर्क के बारे में हैं। के साथ उपयोग करने वाले प्रकारों पर उनके परिणाम विपरीत हैं। एक ऊपरी बाउंड वाइल्डकार्ड (extends
) उन चर के प्रकारों पर निचला बाध्य है जो आप वापसी मान असाइन कर सकते हैं। निचले बाउंड वाइल्डकार्ड (super
) पैरामीटर के रूप में आप जिन प्रकारों को पारित कर सकते हैं उन पर ऊपरी सीमा है। predicate.test(new Object())
संकलित नहीं होगा क्योंकि String
की निचली सीमा के साथ, यह केवल String
के उप-वर्ग स्वीकार करेगा।
'संकलित करता है' भी - 'भविष्यवाणी करें स्ट्रिंग> predicate = s -> s.starts के साथ ("g") '- हालांकि, हम इस predicate के लिए' स्ट्रिंग' फ़ीड नहीं कर सकते हैं :) यह भी देखें [लेख] (http://bayou.io/draft/ कैप्चरिंग_Wildcards.html) वाइल्डकार्ड पर – ZhongYu
http://stackoverflow.com/questions/33085151/bad-return-type-in-lambda-expression/33085893#33085893 – ZhongYu
'पूर्वानुमान सुपर स्ट्रिंग> 'करता है * नहीं * यह दर्शाता है कि आप इसे 'ऑब्जेक्ट' पास कर सकते हैं (और ऐसा करने का प्रयास एक कंपाइलर त्रुटि उत्पन्न करेगा)। हस्ताक्षर 'भविष्यवाणी सुपर स्ट्रिंग> 'बस इसका तात्पर्य है कि यह *