2012-03-23 26 views
5

मैं जावा जेनिक्स और कलेक्शन द्वारा मौरिस नाफ्टालिन, फिलिप वाडलर द्वारा पुस्तक पढ़ रहा था, और पहले दो अध्यायों में मैंने अपने सिर को संदेह से गड़बड़ कर लिया। मैं जवाब जानने में सक्षम नहीं था।प्रकार पैरामीटर के डेटाटाइप को कॉन्वर्सिस और contravariance में कैसे तय किया गया है?

कॉल में:

public static <T> void copy(List<? super T> dst, List<? extends T> src) { 
for (int i = 0; i < src.size(); i++) { 
dst.set(i, src.get(i)); 
} 
} 


List<Object> objs = Arrays.<Object>asList(2, 3.14, "four"); 
List<Integer> ints = Arrays.asList(5, 6); 
Collections.copy(objs, ints); 
assert objs.toString().equals("[5, 6, four]"); 

समारोह 'प्रतिलिपि' के लिए कॉल के दौरान:
1 पैरामीटर: = वस्तु
2 पैरामीटर:? = पूर्णांक

लेकिन डेटाप्रकार क्या है टी का? क्षरण कार्यान्वयन के आधार पर यह जेवीएम द्वारा कैसे तय किया जाता है? लाइन Collections.copy में (obj, ints), प्रकार पैरामीटर टी संख्या होने के लिए लिया जाता है:

यह पुस्तक कि में कहा जाता है। कॉल की अनुमति दी है क्योंकि objs टाइप सूची < वस्तु > है, जो सूची की एक उप-प्रकार है < ? सुपर संख्या > (के बाद से वस्तु संख्या की एक महाप्रकार है, के रूप में सुपर द्वारा आवश्यक) और ints है टाइप सूची < पूर्णांक है >, जो सूची < ? का एक उप प्रकार है, संख्या > बढ़ाता है (चूंकि इंटेगर संख्या का उप प्रकार है, जैसा वाइल्डकार्ड विस्तारित करता है)।

लेकिन पूर्णांक Serializable और तुलनीय लागू करता है के रूप में दोनों, संख्या वर्ग और ऑब्जेक्ट वर्ग का विस्तार से aprt Serializable और तुलनीय भी की सुपर प्रकार है।

तो क्यों नहीं टी को संख्या के बजाय सीरियलज़ेबल या तुलनात्मक के रूप में लिया जाता है, क्योंकि प्रतिस्थापन सिद्धांत इसे लेने की अनुमति देगा।

अग्रिम धन्यवाद।

+0

कारण है कि यह फर्क पड़ता है कि वास्तव में क्या टी है में है कि चयन कर सकते हैं? जेनरिक का उपयोग केवल संकलन-समय पर टाइपिंग जांच के लिए किया जाता है, इसलिए संकलक को केवल यह ध्यान रखना चाहिए कि * कुछ * टी काम करता है; इसके अलावा इससे कोई फर्क नहीं पड़ता – newacct

उत्तर

1

टी तर्कों पर आधारित फैसला किया है लेकिन साथ ही स्पष्ट रूप से निर्दिष्ट किया जा सकता है, वास्तव में है। तो, हाँ यह तुलनात्मक और serializable हो सकता है।

इन सभी मान्य हैं:

 Collections.<Number>copy(objs, ints); 
    Collections.<Comparable>copy(objs, ints); 
    Collections.<Serializable>copy(objs, ints); 
    Collections.<Integer>copy(objs, ints); 

    Collections.copy(objs, ints); // implicitly Integer 

जब कोई प्रकार के तरीके के कारण <? extends Integer> नियंत्रित किया जाता है करने के लिए पूर्णांक उठाया जाता है निर्दिष्ट और java documentation

+0

लेकिन यहां मेरे कार्य में, टी का डाटाटाइप नंबर है। मैं जानना चाहता हूं कि कैसे। यदि स्पष्ट रूप से घोषित किया गया है, जैसा आपने किया है, तो यह Serializable या तुलनात्मक हो सकता है .. मुझे पता है कि हिस्सा। –

+0

आपको इसकी संख्या क्या लगता है? यह उन प्रकारों में से कोई भी हो सकता है लेकिन संख्या एक बेहतर उदाहरण है इसलिए मुझे लगता है कि पुस्तक में इसका उल्लेख क्यों किया गया है। – Andrejs

+0

आप सही हो सकते हैं, भाषा कहती है "टी को संख्या माना जाता है"। इसलिए भाषा का उल्लेख नहीं है कि टी वास्तव में संख्या है। यह मामला हो सकता है। लेकिन अभी भी सवाल यह है कि यह बनी हुई है। टी के डेटाटाइप को मेरे प्रश्न में वर्णित फ़ंक्शन को कॉल करने का क्या अर्थ है, बिना पैरामीटर का स्पष्ट रूप से उल्लेख किए? –

-1

वस्तु वर्ग Serializable और भी
यह सच Serializable और तुलनीय नहीं है कर रहे हैं तुलनीय इंटरफेस की सुपर प्रकार है और वस्तु के साथ कोई रिश्ता नहीं है।

इसके अतिरिक्त super ? यह इंटरफेस के लिए लागू नहीं किया जा सकता है जिसका अर्थ है extends ? की सटीक उल्टा होता है। इसे इंटरफेस पर लागू किया जा सकता है।

जब आप ? extends T लिखते हैं तो इसका अर्थ है ? is an unknown subtype of T, probably T itself। मेरा मानना ​​है कि JVM संकल्प टी नीचे है जिसका अर्थ है T वास्तव में IntegerNumber नहीं है (यदि मैं गलत हूं तो मुझे सही करें)।

फिर

Collections.copy(objs, ints) 

Collections.<Integer>(objs, ints) 
+0

यदि आप वापसी प्रकार को शून्य से टी में बदलते हैं तो यह टी को इंटीजर के रूप में हल करता है। – benmmurphy

+0

मुझे समझ में नहीं आता है। क्या आप कृपया समझा सकते हैं? – UmNyobe

+0

मैंने एक उत्तर जोड़ा है जो रिटर्न प्रकार को बदलता दिखाता है और मैंने कंपाइलर को बारफ करने के लिए मजबूर करने के लिए एक संकलन त्रुटि जोड़ा है जो रिटर्न प्रकार है। – benmmurphy

3

http://docs.oracle.com/javase/specs/jls/se7/jls7.pdf

में विस्तार से बताया से 'सरल' है उदाहरण के लिए जेएलएस का कहना है कि यह सबसे विशिष्ट प्रकार चुनता है जो उत्पन्न होने वाली सभी बाधाओं को पूरा करता है।

15.12.2.7 का निष्कर्ष निकालते प्रकार तर्क वास्तविक तर्क के आधार पर

एक महाप्रकार बाधा टी:> एक्स का तात्पर्य है कि समाधान टी पर कई बाधाओं को देखते हुए, हम कर सकते हैं एक्स के में से एक supertypes है प्रत्येक बाधाओं द्वारा उल्लिखित सुपरटेप के सेट को छेड़छाड़ करें, क्योंकि टाइप पैरामीटर उन सभी का सदस्य होना चाहिए। हम तो सबसे विशिष्ट प्रकार चौराहे

Copy.java:11: incompatible types 
found : java.lang.Integer[] 
required: java.lang.String[] 
    String[] res = copy(Arrays.<Object>asList(2, 3.14, "four"), Arrays.asList(5, 6)); 
        ^
1 error 
➜ /tmp cat Copy.java 
import java.util.*; 
public class Copy { 
public static <T> T[] copy(List<? super T> dst, List<? extends T> src) { 
    for (int i = 0; i < src.size(); i++) { 
     dst.set(i, src.get(i)); 
    } 

    return null; 
    } 
    public static void main(String[] args) { 
    String[] res = copy(Arrays.<Object>asList(2, 3.14, "four"), Arrays.asList(5, 6)); 
    } 

} 
+0

लेकिन यह अलग है। आप स्ट्रिंग को वापस करने के लिए प्रतिलिपि बना रहे हैं [] ताकि टी को स्ट्रिंग करने के लिए मजबूर किया जा सके ... यह संबंधित नहीं है। – UmNyobe

+0

मैं टी को स्ट्रिंग करने के लिए मजबूर नहीं कर रहा हूं। संकलक वास्तव में शिकायत कर रहा है कि यह स्ट्रिंग नहीं है।मैंने अभी रिटर्न प्रकार और जानबूझकर टाइप त्रुटि को संकलक को ट्रिक करने के लिए जोड़ा है जो टी के प्रकार के बारे में सोचता है। "मिला: java.lang.Integer []" .. मुझे सरणी प्रकार को रिटर्न प्रकार से हटा देना चाहिए था लेकिन वहां है। – benmmurphy

+0

लेकिन मुझे अभी भी यह नहीं मिला है, यह कैसे तय किया जाता है? क्या आप निर्णय के प्रवाह की व्याख्या कर सकते हैं, यह तीन विकल्पों में तुलना कैसे कर रहा है- तुलनात्मक, सीरियलज़ेबल, संख्या और इंजेगर? –