2015-05-28 6 views
11

हम वर्तमान में जावा 7 से जावा 8 तक किसी एप्लिकेशन को माइग्रेट करने की प्रक्रिया में हैं। कुछ संकलन समस्याओं को ठीक करने के बाद, मैंने निम्नलिखित प्रश्न के समान एक समस्या पर ठोकर खाई: ClassCast Error: Java 7 vs Java 8अस्पष्ट विधि कॉल का पता कैसे लगाएं जो जावा 8 में क्लासकास्ट अपवाद का कारण बनता है?

public class Test { 
    public static void main(String[] args) { 
     System.out.println(String.valueOf(getVal("xxx"))); // 7: prints the result, 8: Exception 
    } 

    @SuppressWarnings("unchecked") 
    public static <T> T getVal(String param) { 
     // do some computation based on param... 
     return (T) result; // actual return type only depends on param so the caller knows what to expect 
    } 
} 

विचार हम जोर होता है कि कि फोन करने वाले की उम्मीद प्रकार जानता था, और यह उसे एक स्पष्ट कलाकारों से बच जाएंगे (मैं:

संक्षेप में, यहाँ एक नमूना कोड कि इस मुद्दे से पता चलता है यह मत कहें कि यह एक अच्छा विचार था ...)। कई मामलों में, कॉलर को सिर्फ Object की उम्मीद है, इसलिए कोई अंतर्निहित कलाकार नहीं था।

ऊपर दिए गए प्रश्न में बताया गया है कि String.valueOf उदाहरण जावा 7 में ठीक काम करता है क्योंकि कोई प्रकार अनुमान नहीं था, इसलिए Object माना गया था। अब जावा 8 में, कंपाइलर सबसे विशिष्ट प्रकार चुनता है (यहां char[]), जो रनटाइम पर ClastCastException का कारण बनता है।

समस्या यह है कि हमारे पास इस getVal विधि के लगभग 350 कॉल हैं। क्या ओवरलोडेड विधि कॉल का पता लगाने का कोई तरीका है जो जावा 7 और जावा 8 के बीच अलग होगा? आईई। पता लगाएँ कि जावा 8 कंपाइलर जावा 7 कंपाइलर से एक अलग विधि का चयन करेगा।

+2

हमारे पास एक समान विधि थी जिसे सैकड़ों स्थानों में भी बुलाया गया था। मैंने इसे अतिरिक्त 'कक्षा क्लैज' पैरामीटर पेश करने की जगह बदल दी। इस तरह से आप एक स्पष्ट त्रुटि हैंडलिंग कर सकते हैं: या तो शून्य वापस या कुछ और विशिष्ट अपवाद फेंक दें। मैंने इसे मैन्युअल रूप से आधे घंटे की तरह खर्च किया। मैं आपको ऐसा करने की सलाह देता हूं। मुझे नहीं पता कि इसे कैसे स्वचालित किया जाए, इस प्रकार यह आपके प्रश्न के उत्तर के रूप में योग्य नहीं है। –

+2

एक साधारण उत्तर है: * "अनचेक" चेतावनियां दबाएं *। वे पहले से ही आपको बताते हैं कि आपका कोड गलत है। यदि आप अब अपना कोड ठीक करना चाहते हैं कि यह बहुत देर हो चुकी है, तो बस '@SuppressWarnings ("अनचेक") की घटनाओं की खोज करें ... – Holger

+0

@ होल्गर क्या आप कृपया 2011 में इसे लागू करने के दौरान अपने सहयोगी को बता सकते हैं? ;-) मुझे पहले से ही पता था कि यह पहली जगह में एक बुरा विचार था (हालांकि यह उतना बुरा नहीं है जितना अब जावा 8 में है)। साथ ही, विधि कॉल पर स्वयं '@ SuppressWarnings' नहीं है, यह केवल 'getVal' की घोषणा में है। इस एनोटेशन को हटाने से इस प्रकार कोई समस्याग्रस्त उपयोग नहीं दिखाया जाएगा। –

उत्तर

2

एक बेहतर विकल्प होगा:

public class Test { 
    public static void main(String[] args) { 
     System.out.println(String.valueOf(getVal("xxx"))); // 7: prints the result, 8: Exception 
    } 

    @SuppressWarnings("unchecked") 
    public static <T> T getVal(T param) { 
     // do some computation based on param... 
     return param; // actual return type only depends on param so the caller knows what to expect 
    } 
} 

जो दोनों जावा 7 और जावा 8.

+0

यह एक विकल्प नहीं है क्योंकि आप लगाते हैं कि रिटर्न प्रकार पैरामीटर के समान है (जो मेरे मामले में 'स्ट्रिंग' है और मैं इसे _easily_ बदल नहीं सकता)। साथ ही, उन मामलों की पहचान करना है जहां उन सभी को बदलने या हाथ से खोजने से बचने के लिए जावा 7 और 8 के बीच अधिभारित विधि कॉल अलग हैं। –

1

में काम करेंगे अंत में समाधान getVal() बदलने के लिए वापस जाने के लिए था Object:

public static Object getVal(String param) { 
     // do some computation based on param... 
     return result; 
    } 

और एक दूसरी विधि जोड़ें जो वांछित कक्षा को पैरामीटर के रूप में भी लेती है:

public static <T> T getVal(String param, Class<T> clazz) { 
     return clazz.cast(getVal(param)); 
    } 

तो उचित कक्षा पैरामीटर जोड़कर सभी संकलन मुद्दों को ठीक करें (जहां कॉलर Object की अपेक्षा नहीं करता)।

एक कलाकार डालने से भी काम किया होगा, लेकिन इससे बिना शर्त परिस्थितियों के लिए कई चेतावनियां हुईं। बिना शर्त कास्ट वास्तव में अभी भी है (clazz पैरामीटर के माध्यम से), लेकिन यह उन सभी कॉलर्स को आसानी से पहचानने की अनुमति देता है जिन्हें कलाकारों को 2 पैरामीटर के साथ विधि का उपयोग करने की आवश्यकता होती है।

इसके अतिरिक्त - और यह इस मामले को बहुत विशिष्ट है - ऐसा लगता है कि param ही अक्सर कुछ TypedParam<T> जहां TgetVal() की उम्मीद वापसी प्रकार भी था, और जो टी के वर्ग निहित पर एक विधि कॉल का परिणाम था।

मैं इस प्रकार एक अतिरिक्त सुविधा विधि को लागू कर सकते हैं:

public static <T> T getVal(TypedParam<T> param) { 
     return getVal(param.stringValue(), param.getValueClass()); 
    } 

और बस getVal(param) द्वारा सभी getVal(param.stringValue()) बदल दिया।

यह समाधान सामान्य मामले को हल नहीं करता है - अतिभारित विधि कॉल है कि जावा 7 और जावा 8 के बीच भिन्न हैं का पता लगाने - लेकिन यह तरीकों कि इस समस्या का कारण जाना जाता है के लिए यह हल करता है। और तब से हमें यह कहीं और नहीं मिला।

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