2017-03-04 18 views
6

मैं इस सामान्य कार्य हो: इस कोड के साथ मुख्य रूप सेवापसी प्रकार (जावा)

public static <T extends Number> T sum(List<T> list){ 
    Number tot = 0; 
    for(Number n: list){ 
     tot = tot.doubleValue() + n.doubleValue(); 
    } 
    return (T)tot; 
} 

याद:

public static void main(String[] args) { 
    ArrayList<Integer> listInt = new ArrayList<>(); 
    listInt.add(3); 
    listInt.add(5); 
    listInt.add(6); 
    listInt.add(8); 
    System.err.println("Sum: " + Calcolatrice.sum(listInt)) 
} 

इसलिए मैं (listInt पूर्णांकों का एक ArrayList जा रहा है) की उम्मीद कि फ़ंक्शन योग द्वारा लौटाया गया मान टी = इंटीजर है और इस मामले में, मुझे डबल से इंटीजर में एक रूपांतरण त्रुटि दें। परिणाम का प्रकार बदले में डबल है और कोई त्रुटि नहीं फेंक दी गई है। कास्ट (टी) कुल वांछित परिणाम नहीं है।

मुझे लगता है कि ऐसा इसलिए है क्योंकि जावा जेनेरिक स्टेंस चरण को संभालता है, लेकिन कोई बेहतर ढंग से समझाता है कि यह इस तरह क्यों काम करता है?

+4

[प्रकार विलोपन] (https://docs.oracle.com/javase/tutorial/java/generics/erasure.html) वह शब्द है जो व्यवहार को बताता है .... –

उत्तर

1

Calcolatrice.sum(listInt) की वापसी प्रकार वास्तव में अपने उदाहरण में sum के अंत में कलाकारों को Integer धन्यवाद है। हालांकि परिणाम का असली प्रकार Double है। जाहिर है यह एक अच्छी स्थिति नहीं है, लेकिन ऐसा इसलिए हुआ क्योंकि आपने स्पष्ट रूप से कलाकार में संकलक को बताया कि रिटर्न वैल्यू के पास रिटर्न वैल्यू के समान प्रकार होगा।

यह स्थिति मतलब है कि अगर आप के बजाय Calcolatrice.sum(listInt).toString() लिखने के थे आप एक ClassCastException: java.lang.Double cannot be cast to java.lang.Integer मिलेगा क्योंकि आप एक Double पर Integer.toString() बुला लिया जाएगा। आपका कोड वास्तव में क्या कर रहा है System.out.println("Sum: "+ String.valueOf(Calcolatrice.sum(listInt))) है जो काम करता है क्योंकि यह toString पर कॉल करने से पहले Object (इस प्रकार संघर्ष को हल करता है) को घटा देता है।

@TmTron बताते हैं कि आप Double और Integer बॉक्सिंग प्रकारों के बीच उसी तरह से नहीं डाले जा सकते हैं जैसा आप प्राइमेटिव के साथ कर सकते हैं।

यानी

int i = (int) 2.0; 

से अलग नियम इस प्रकार है:

Integer i = (Integer) new Double(2.0) 
3

जेनिक्स केवल यह सुनिश्चित करने के लिए संकलन में उपयोग किया जाता है कि आप अपने कोड में गलती नहीं कर रहे हैं: यहां, पैरामीटर List<T> है, और प्राप्त करने वाला चर T प्रकार होना चाहिए। बस इतना ही।

रनटाइम के दौरान, T मौजूद नहीं है, और totT का उदाहरण नहीं है; यह Number है।

आप अपरिभाषित उदाहरण प्राप्त करने के लिए अपनी विधि के अंदर T का उपयोग कर सकते हैं, उदाहरण के लिए, आप new T() नहीं बना सकते हैं।

3

आप प्रकार पदानुक्रम को देखते हैं तो आप देखते हैं कि Integer और Double दोनों Number के बच्चे हैं: तो वे भाई बहन हैं और आप नहीं सीधे Integer करने के लिए Double डाली कर सकते हैं:

Double testDbl = 3.14; 
    Integer testInt = (Integer)testDbl; // this will NOT compile 

संकलक निश्चित रूप से पता नहीं कर सकते, यदि आपका sum समारोह की वापसी बयान में डाली काम करते हैं या असफल हो जायेगी: लेकिन संकलक एक चेतावनी दिखाएगा:

Unchecked cast: 'java.lang.Number' to 'T' 

क्योंकि हार्ड-कास्ट (T)tot का, संकलक इसे केवल यह मानने के लिए ले जाएगा कि आपका फ़ंक्शन Integer (जो यह नहीं करता) देता है।

और अंत में, type erasure की वजह से, कोई रनटाइम चेक नहीं है।

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