2016-07-19 6 views
11

पर कास्टिंग मैं सामान्य और कास्टिंग समझता हूं लेकिन मैं सामान्य कास्टिंग को समझ नहीं पा रहा हूं। मैंने सोचा कि मैं केवल विशिष्ट प्रकार अप करने के लिए या नीचे inheritence पेड़ के माध्यम से डाल सकता है, लेकिन यह मुझे गलत साबित कर दिया:सामान्य चर

ArrayList<?> cislo = (ArrayList<? extends Number>) new ArrayList<Integer>(); 

यह सबसे अच्छा उदाहरण नहीं हो सकता है, लेकिन उम्मीद है कि आप मेरी बात मिल जाएगा। यह कैसे काम करता है? किस प्रकार इसे कास्ट किया जाता है?

+1

देखें रन समय वहाँ कोई डाली बिल्कुल है, के रूप में सामान्य जानकारी (प्रकार विलोपन) खो दिया है। संकलन समय पर आप 'ArrayList ' को 'ArrayList <' के रूप में संभालने के लिए संकलक को बताते हैं? संख्या> 'बढ़ाता है और इसके बारे में चुप रहें (चेतावनी को छोड़कर, मूल रूप से यह वही है जैसे आप 'संख्या' चर को 'इंटीजर' पर डालेंगे - आप संकलक को बताते हैं कि आप जानते हैं कि आप क्या कर रहे हैं)। 'ArrayList 'के लिए असाइनमेंट किसी भी मामले में काम करता है। जेनरिक्स के साथ – Thomas

+0

, कास्टिंग बिल्कुल जरूरी नहीं होना चाहिए। यदि आप जेनेरिक प्रकार कास्टिंग करना पसंद करते हैं, तो शायद आपको यह जांचना चाहिए कि विशाल लचीलापन जेनरिक का उपयोग करके केवल "साफ" समाधान नहीं है या नहीं। मुझे यकीन है कि यदि आपके पास एक विशिष्ट उदाहरण है तो बहुत से लोग मदद करने के लिए तैयार होंगे। – martinhh

+0

मेरे पास विशिष्ट उदाहरण है। मैं framwork जो JUnit परीक्षण टिप्पणी करने के लिए भंडारण मैं '@ReesmoConfiguration (भंडारण = RestApiStorage.class) जैसे करने के लिए' और अमूर्त सुपर क्लास संग्रहण में मैं कारखाने विधि 'newInstance (वस्तु विन्यास) { परिणाम मिले भेजना चाहते हैं का चयन करने के लिए अनुमति देता है के साथ काम कक्षा क्लैज = शून्य खींचता है; यदि (Bool.FALSE.equals (Property.ENABLED.get (कॉन्फ़िगरेशन))) { क्लैज = डमीस्टॉरेज.क्लास; } अन्य { क्लैज = (कक्षा ) Property.STORAGE.get (कॉन्फ़िगरेशन); } अगर (clazz.isAssignableFrom (DummyStorage.class)) { नई DummyStorage वापसी(); }} ' –

उत्तर

4

कलाकार अनावश्यक है।

कार्य

ArrayList<?> list = new ArrayList<Integer>(); 
ArrayList<? extends Number> list2 = new ArrayList<Integer>(); 

किसी भी स्पष्ट कास्टिंग की आवश्यकता नहीं है।

वाइल्डकार्ड प्रकार "क्या अधिक सामान्य" ठोस प्रकार से/"कम विशिष्ट" प्रकार के होते हैं, और upper bounded wildcard types (? extends Number की तरह) unbounded ones (?) की तुलना में अधिक विशिष्ट हैं।

वाइल्डकार्ड प्रकारों के बीच संबंधों के बारे में अधिक जानकारी Oracle Tutorial on Wildcards and Subtyping में मिल सकती है।

JLS इस निर्दिष्ट करने के प्रासंगिक भाग 4.10.2. Subtyping among Class and Interface Types

है एक सामान्य प्रकार घोषणा सी (एन> 0) को देखते हुए, पैरामिट्रीकृत प्रकार सी, जहां ती (1 ≤ मैं n ≤) के प्रत्यक्ष supertypes = टी 1, Fn ...,:

  • डी, जहां विकास के लिए एक सामान्य प्रकार है जो सामान्य प्रकार सी और θ का एक सीधा महाप्रकार है प्रतिस्थापन [F1 है: एक प्रकार है, निम्न में से सभी कर रहे हैं : = Tn]।
  • सी, जहां सी में टीआई (1 ≤ i ≤ n) (§4.5.1) शामिल है।

[...]

जो, 4.5.1. Type Arguments of Parameterized Types

एक प्रकार तर्क टी 1 एक अन्य प्रकार के तर्क टी 2 शामिल करने के लिए कहा जाता है, लिखा टी 2 < = टी 1 के लिए संदर्भित करता है, तो सेट टी 2 द्वारा दर्शाए गए प्रकारों का उल्लेखनीय रूप से निम्नलिखित नियमों के रिफ्लेक्सिव और ट्रांजिटिव क्लोजर के तहत टी 1 द्वारा निर्दिष्ट प्रकारों के सेट का एक सबसेट है (जहां <: सबटाइपिंग (§4.10) दर्शाता है:

  • ? टी < = विस्तारित करता है? एस अगर टी <: एस

  • ? टी < = विस्तारित करता है?

[...]

तो यह परिभाषा ArrayList<? extends Number> द्वारा ArrayList<Integer> और ArrayList<?> के महाप्रकार है कच्चे प्रकार को छोड़कर किसी भी ArrayList<> के महाप्रकार है।

एक प्रकार के चर के लिए असाइनमेंट जो सुपरर्ट टाइप है उसे कास्टिंग की आवश्यकता नहीं होती है।


एक डाली आवश्यक हो तो आप एक अलग तरह के कुछ प्रदान करना चाहते हैं है:

Object list = new ArrayList<Integer>(); 
//...somewhere else - the compiler does not know that list is always an ArrayList, but we tell it that we know what we are doing 
List<? extends Number> numbers = (List<? extends Number>) list; //unchecked cast warning, but works 

कि कलाकारों के बाद, आप जैसे कर सकते हैं सूची से तत्व प्राप्त करें और उन्हें Number एस के रूप में देखें। कलाकारों रनटाइम पर विफल हो जाएगा यदि आप फेंकने

java.lang.ClassCastException: java.util.HashSet cannot be cast to java.util.List


में समस्या आने पर शुरू करते हैं जो List<? extends Number>

Object list = new HashSet<Integer>(); 
    List<? extends Number> numbers = (List<? extends Number>) list; //unchecked cast warning 

की एक उप प्रकार नहीं है list संदर्भ के लिए कुछ और रन टाइम पर विफल रहता है आवंटित जब सामान्य प्रकार से मेल नहीं खाता:

List<String> stringList = new ArrayList<String>(); 
stringList.add("hi"); 
Object list = stringList; 
List<? extends Number> numbers = (List<? extends Number>) list; //unchecked cast warning, but (sadly) works 

Number n = numbers.get(0); //fails: java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Number 

ऐसा इसलिए होता है क्योंकि रनटाइम पर, सूची-प्रकार मिलानों का मिटा। भी the tutorial on erasure

+0

" कास्ट अनावश्यक है। " - जैसा कि मैंने कहा कि सबसे अच्छा उदाहरण नहीं हो सकता है। मैं जेएलएस को पढ़ने के लिए वास्तव में मुश्किल लगता है, लेकिन आपकी व्याख्या वास्तव में मदद की, thx। अतिरिक्त जानकारी यहां मिल सकती है http://stackoverflow.com/questions/2776975/how-can-i-add-to-list-extends-number-data- संरचनाएं –

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