2010-10-16 26 views
6

(कोई सलाह दें कि मैं चाहिए सार X अधिक है और यह करने के लिए एक और तरीका जोड़ें।)जावा: संयुक्त उदाहरण और कास्ट?

सी ++ में, जब मैं प्रकार के एक चर x है और मैं कुछ विशिष्ट करना चाहते हैं यह प्रकार Y* की भी है (YX का एक उपवर्ग जा रहा है), मैं इस लिख रहा हूँ: (? या यह है)

if(Y* y = dynamic_cast<Y*>(x)) { 
    // now do sth with y 
} 

एक ही बात जावा में संभव नहीं लगता है।

मैं बजाय इस जावा कोड को पढ़ लिया है:

if(x instanceof Y) { 
    Y y = (Y) x; 
    // ... 
} 

कभी कभी, आप एक चर x की जरूरत नहीं है जब, लेकिन यह सिर्फ इस समस्या के कारण के बजाय एक अधिक जटिल अभिव्यक्ति है, है, तो आप एक डमी चर की जरूरत है जावा में:

X x = something(); 
if(x instanceof Y) { 
    Y y = (Y) x; 
    // ... 
} 
// x not needed here anymore 

(आम बात यह है कि something()iterator.next() है और वहाँ आप देखते हैं कि आप भी वास्तव में सिर्फ दो बार है कि फोन नहीं कर सकते हैं आप वास्तव में डमी चर की जरूरत है।।।)

01,235,

आपको वास्तव में x की ज़रूरत नहीं है - आपको बस यह है क्योंकि आप instanceof को कलाकार के साथ एक बार जांच नहीं सकते हैं। कि तुलना बहुत आम सी ++ कोड के लिए फिर से:

if(Y* y = dynamic_cast<Y*>(something())) { 
    // ... 
} 
इस वजह से

, मैं एक castOrNull समारोह जो यह संभव डमी चर x से बचने के लिए बनाता है शुरू की है। अब मैं यह लिख सकते हैं: castOrNull की

Y y = castOrNull(something(), Y.class); 
if(y != null) { 
    // ... 
} 

कार्यान्वयन:

public static <T> T castOrNull(Object obj, Class<T> clazz) { 
    try { 
     return clazz.cast(obj); 
    } catch (ClassCastException exc) { 
     return null; 
    } 
} 

अब, मुझे बताया गया था कि using this castOrNull function in that way is an evil thing do to। ऐसा क्यों है? (या प्रश्न अधिक सामान्य डाल करने के लिए: यदि आप बात से सहमत हैं और यह भी लगता है कि इस बुराई है यदि हाँ, क्यों इतनी या आपको लगता है कि यह एक वैध (शायद दुर्लभ मामला) का उपयोग है???)


के रूप में कहा , मैं एक चर्चा नहीं चाहता हूं कि इस तरह के डाउनकास्ट का उपयोग बिल्कुल अच्छा विचार है। लेकिन मुझे शीघ्र ही स्पष्ट कारण है कि मैं कभी कभी इसका इस्तेमाल करते हैं:

  1. कभी कभी मैं इस मामले में जहां मैं (एक बहुत ही विशेष बात के लिए एक और नई विधि जोड़ने जो केवल एक में एक ही उपवर्ग के लिए लागू होगी के बीच चयन करने के लिए है में मिल विशिष्ट मामला) या instanceof चेक का उपयोग कर। असल में, मेरे पास doSomethingVeryVerySpecificIfIAmY() फ़ंक्शन जोड़ने या instanceof चेक करने के बीच विकल्प है। और ऐसे मामलों में, मुझे लगता है कि उत्तरार्द्ध अधिक स्वच्छ है।

  2. कभी-कभी मेरे पास कुछ इंटरफ़ेस/बेस क्लास का संग्रह होता है और Y के सभी प्रविष्टियों के लिए, मैं कुछ करना चाहता हूं और फिर उन्हें संग्रह से हटा देना चाहता हूं। (उदा मैं इस मामले में जहां मैं एक वृक्ष संरचना था और मैं सभी बच्चे जो खाली लीफ़्स हैं नष्ट करने के लिए चाहता था।)

+1

मैं _class.cast_ के बजाय _instanceOf_ का उपयोग _castOrNull_ में अनावश्यक अपवाद से बचने के लिए होगा, लेकिन अलग से आप पूरी तरह से सामान्य सहायक है लगता है कि। चलो ** टॉम ** स्पष्ट करें कि उसका क्या मतलब था। –

+0

यदि वाई एक्स का _superclass_ है, तो आपको बिल्कुल कोई कलाकार नहीं चाहिए - क्या आपका मतलब _subclass_ है? –

+0

हालांकि यह जावा में एक-लाइनर नहीं है, उदाहरण और कास्टिंग का प्रदर्शन काफी अच्छा है। मैं यहां समस्या के विभिन्न दृष्टिकोणों के आसपास जावा 7 में कुछ समय पोस्ट कर रहा हूं: http://stackoverflow.com/questions/16320014/java-optimization-nitpick-is-it-faster-to-cast-something-and-let-it- फेंक-एक्ससेप/28858680 # 28858680 – Wheezil

उत्तर

8

अब, मुझे बताया गया था कि इस तरह से इस castOrNull समारोह का उपयोग कर एक बुरी बात करने के लिए क्या है। ऐसा क्यों है?

मैं कारणों की एक जोड़ी के बारे में सोच सकते हैं:

  • यह बहुत ही सरल कुछ करने का एक अस्पष्ट और मुश्किल रास्ता है। अस्पष्ट और मुश्किल कोड पढ़ने के लिए कठिन है, बनाए रखने में कठोर, त्रुटियों का एक संभावित स्रोत (जब कोई इसे समझ में नहीं आता है) और इसलिए बुराई।

  • castOrNull विधि अस्पष्ट और मुश्किल तरीका जेआईटी कंपाइलर द्वारा अनुकूलित नहीं किया जा सकता है। आप कम से कम 3 अतिरिक्त विधि कॉल के साथ समाप्त हो जाएंगे, साथ ही टाइप करने के लिए बहुत सारे अतिरिक्त कोड को प्रतिबिंबित करें और प्रतिबिंबित करें। प्रतिबिंब का अनावश्यक उपयोग बुरा है।

(इसके विपरीत, सरल (instanceof एक वर्ग डाली जिसके बाद) जिस तरह से instanceof और वर्ग कास्टिंग के लिए विशिष्ट bytecodes उपयोग करता है। बाईटकोड दृश्यों लगभग निश्चित रूप से अनुकूलित किया जाएगा कर सकते हैं ताकि कोई एक से अधिक रिक्त है चेक कोड और ऑब्जेक्ट के प्रकार का एक परीक्षण मूल कोड में नहीं। यह एक सामान्य पैटर्न है जो जेआईटी कंपाइलर का पता लगाने और अनुकूलित करने के लिए आसान होना चाहिए।)

बेशक, "बुराई" बस एक और तरीका है कह रही है कि आपको वास्तव में ऐसा नहीं करना चाहिए।

अपने दो जोड़े गए उदाहरणों में से कोई भी, castOrNull विधि या तो आवश्यक या वांछनीय विधि का उपयोग करें। आईएमओ, "सरल तरीका" पठनीयता और प्रदर्शन दृष्टिकोण दोनों से बेहतर है।

+0

आह, उस जानकारी के लिए धन्यवाद! तो आप यह भी तर्क देंगे कि मुझे 'castOrNull' का उपयोग नहीं करना चाहिए? या आप मेरे दिए गए प्रो-पॉइंट्स के खिलाफ उन अनुबंध-बिंदुओं को कैसे महत्व देंगे? (क्योंकि आखिरकार, डमी वैरिएबल से बचने से भी अधिक पठनीय और छोटा कोड हो सकता है।) – Albert

+1

एकमात्र प्रो पॉइंट जिसे मैं समझ सकता हूं वह कुछ मामलों में अस्थायी चर का उपयोग करने से बचाता है। मेरे लिए, यह पूरी तरह से कॉस्मेटिक मुद्दा है। अस्थायी उपयोग कोड को कम पढ़ने योग्य आईएमओ नहीं बनाता है, और छोटा कोड एक पठनीयता लाभ नहीं है। (और बीटीडब्ल्यू यह एक "डमी" चर नहीं है क्योंकि इसका उपयोग किया जाता है।) –

2

मैं बिल्कुल नहीं जानता कि क्यों उस व्यक्ति ने कहा कि यह बुराई था।हालांकि उनके तर्क के लिए एक संभावना यह थी कि आप कास्ट करने से पहले जांच करने के बजाय बाद में अपवाद प्राप्त कर रहे थे। यह ऐसा करने का एक तरीका है।

public static <T> T castOrNull(Object obj, Class<T> clazz) { 
    if (clazz.isAssignableFrom(obj.getClass())) { 
     return clazz.cast(obj); 
    } else { 
     return null; 
    } 
} 
+0

मुझे संदेह है कि उसका मतलब था क्योंकि मैंने बेहतर कोड और कोड जो मैंने यहां पोस्ट किया है, उसका स्वयं का सुझाव था। – Albert

+0

लिंक के उत्तर में टिप्पणियों में एक समान विकल्प पर चर्चा की गई थी, और टॉम ने इसे उपर्युक्त संस्करण पर पसंद नहीं किया था। –

+0

@ अल्बर्ट: इससे चूक गया ... क्योंकि यह मामला है, मैं कहूंगा कि सबसे अधिक संभावना है कि पेटर का जवाब उपरोक्त डिजाइन का सवाल है। लेकिन वास्तव में, यह पता लगाने के लिए कि क्यों वह मानता है कि यह गलत है, आपको उसकी प्रतिक्रिया का इंतजार करना होगा (यदि वह कभी आपको वापस ले जाता है)। – Thomas

4

IMHO अपने castOrNull बुराई नहीं, बस व्यर्थ है। आप अस्थायी चर और कोड की एक पंक्ति से छुटकारा पाने के साथ भ्रमित प्रतीत होते हैं, जबकि मेरे लिए बड़ा प्रश्न है, आपको अपने कोड में इतने सारे डाउनकास्ट क्यों चाहिए? ओओ में यह लगभग हमेशा उपोष्णकटिबंधीय डिजाइन का एक लक्षण है। और मैं लक्षण का इलाज करने के बजाय मूल कारण को हल करना पसंद करूंगा।

+1

ठीक है, जावा में कई पुस्तकालय हैं जिन्हें हम डिज़ाइन नहीं करते हैं, लेकिन इसका उपयोग करना है। (उल्लेख किया गया इटरेटर एक उदाहरण है) –

+0

@ निकिता, उचित है, अगर आप बुरी तरह से डिज़ाइन किए गए हैं लेकिन साथ ही अनिवार्य जावा लाइब्रेरी का उपयोग करते हैं, तो आपके पास शायद ही विकल्प हैं। मेरा व्यक्तिगत अनुमान यह है कि इस तरह के पुस्तकालयों को बहुत दुर्लभ होना चाहिए। यदि लाइब्रेरी का उपयोग करने के लिए यह अजीब है, तो कोई भी इसका उपयोग नहीं करता है, या जल्दी या बाद में कोई बेहतर विकल्प विकसित करना शुरू कर देता है। –

+0

मैंने अपने प्रश्न को 2 मामलों को दिखाने के लिए थोड़ा बढ़ा दिया है जहां मैं कभी-कभी इसका उपयोग करता हूं। मुझे वास्तव में वास्तव में कठिन नियम पसंद नहीं हैं ** कभी भी ** कभी भी उपयोग न करें और मुझे लगता है कि मेरे प्रदान किए गए दो मामले वैध मामले हैं जहां आप इसे ऐसा कर सकते हैं। आप मेरे बारे में इस बारे में अधिक चरम हो सकते हैं लेकिन मुझे लगता है कि आप इस तरह के कोड का कभी भी उपयोग करने के लिए इतने चरम नहीं होंगे। और फिर, यदि आपके पास ऐसा कोई मामला है, तो मुझे हमेशा सबसे साफ समाधान होना पसंद है और यही वह है जो मैं यहां पूछ रहा हूं। :) – Albert

5

सबसे अच्छी तरह से लिखित/डिज़ाइन किए गए जावा कोड में उदाहरण और उपयोग का उपयोग कभी नहीं होता है। जेनेरिक के अतिरिक्त केस्ट के कई मामलों (और इस प्रकार उदाहरण) की आवश्यकता नहीं है। वे करते हैं, अवसर पर अभी भी होते हैं।

CastOrNull विधि बुरा है कि आप जावा कोड को "अप्राकृतिक" बना रहे हैं। एक भाषा से दूसरी भाषा में बदलते समय सबसे बड़ी समस्या नई भाषा के सम्मेलनों को अपना रही है। अस्थायी चर जावा में ठीक हैं। वास्तव में आपकी सभी विधि वास्तव में अस्थायी चर छुपा रही है।

यदि आप पाते हैं कि आप बहुत सारे कलाकार लिख रहे हैं तो आपको अपने कोड की जांच करनी चाहिए और देखें कि उन्हें हटाने के तरीकों का क्यों और देखें। उदाहरण के लिए, यदि आप "getNumberOfChildren" विधि जोड़ने का उल्लेख करते हैं तो आपको यह जांचने की अनुमति होगी कि कोई नोड खाली है या नहीं, इस प्रकार इसे कास्टिंग किए बिना इसे छीनने में सक्षम है (यह अनुमान है, यह आपके लिए इस मामले में काम नहीं कर सकता है)।

आम तौर पर बोलने वाले जानवर जावा में "बुरा" होते हैं क्योंकि उन्हें आम तौर पर आवश्यकता नहीं होती है। आपकी विधि अधिक "बुराई" है क्योंकि यह इस तरह से लिखा नहीं गया है कि अधिकांश लोग जावा को लिखे जाने की अपेक्षा करेंगे।

कहा जा रहा है कि, यदि आप इसे करना चाहते हैं, तो इसके लिए जाएं। यह वास्तव में जावा में ऐसा करने के लिए "बुरा" नहीं है "सही" तरीका नहीं है।

0

जावा अपवाद धीमे हैं। यदि आप डबल कलाकार से बचकर अपने प्रदर्शन को अनुकूलित करने का प्रयास कर रहे हैं, तो आप लॉजिक के बदले अपवादों का उपयोग करके पैर में खुद को शूटिंग कर रहे हैं। किसी ऐसे चीज के लिए अपवाद को पकड़ने पर भरोसा न करें जिसे आप उचित रूप से जांच सकते हैं और सही कर सकते हैं (ठीक है आप क्या कर रहे हैं)।

How slow are Java exceptions?

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