2011-01-24 16 views
9

मेरे पास निम्न पैटर्न के साथ कुछ कोड है:क्या यह शून्य शैली के लिए NullPointerException का उपयोग करने के लिए खराब शैली है?

return a().b().c().d().e(); 

अब चूंकि उन सभी विधियों में null वापस आ सकता है, इसलिए आमतौर पर इसका परीक्षण किया जाएगा:

if((a()!=null) && (a().b() != null) && ....) { 
    return a().b().c().d().e(); 
} else { 
    return null; 
} 

(और शायद कुछ स्थानीय चर का उपयोग करें डुप्लिकेट कॉल से बचें)

मुझे ऐसा करने का मोह है:

try { 
    return a().b().c().d().e(); 
} catch (NullPointerException e) { 
    return null; 
} 

क्या यह खराब शैली माना जाता है? अक्षम? या ठीक है?

+0

मुझे लगता है कि नियंत्रण प्रवाह को नियंत्रित करने के लिए अपवादों का उपयोग करना बुरा है। – Sweeper

उत्तर

16

ऐसा मत करें। मूल शून्य जांच की तुलना में अपवादों को फेंकना और पकड़ना काफी महंगा है।

आपको यह भी जानने में रुचि हो सकती है कि जावा के भविष्य के संस्करण के लिए वाक्यविन्यास प्रस्तावित किया गया है जो इसे आसान बना देगा। यह कुछ ऐसा होगा:

a()?.b()?.c()?.d() 

"?" ऑपरेशन "।" का एक वैकल्पिक संस्करण होगा। ऑपरेटर। यदि एलएचएस शून्य है, तो वह आरएचएस का मूल्यांकन करने की कोशिश करने के बजाय उस बिंदु पर शून्य वापस आ जाएगा। वास्तव में आप जो खोज रहे हैं, लेकिन मुझे डर है कि उसने जावा 7 के लिए कटौती नहीं की है। जावा 8 के लिए इस फीचर की स्थिति को नहीं जानते।

+0

लेकिन, अगर वह कोशिश करने के साथ ऐसा करता है ... तो, जो भी हो, यह काम करेगा, आपको पता है। हमें एक प्रोग्रामिंग भाषा का उपयोग क्यों नहीं करना चाहिए? और, हाँ, शायद यह शून्य जांच से जांचने के लिए थोड़ा तेज़ होगा, लेकिन फिर भी: यदि भी गति महत्वपूर्ण नहीं है ... –

+1

@Martijn Courteaux: सवाल यह नहीं है कि एनपीई पकड़ने के बारे में सवाल नहीं है। यह स्पष्ट रूप से करता है। प्रश्न यह है कि इस तरह के लेखन कोड की आदत में होना एक अच्छा विचार है। यह नहीं है –

1

शून्य लौटने के बजाय, उनमें से प्रत्येक को दें NullObject या कुछ वापस लौटें। Null Object Pattern के बारे में पढ़ें।

+1

जबकि नल ऑब्जेक्ट उपयोगी हो सकता है, यह कुछ समस्याएं छिपा सकता है और डीबगिंग को कठिन बना सकता है। इसका उपयोग न करें अगर एकमात्र लाभ एक ही स्थान पर दो परीक्षणों को बचा रहा हो। – maaartinus

2

मैं मुख्य रूप से ऐसा नहीं करूँगा क्योंकि a() या b() या c() आदि में एक बग है जो उन्हें NullPointerException को फेंकने का कारण बनती है? उस स्थिति में आप इसे पकड़ रहे हैं और जब आपके पास नहीं होना चाहिए।

2

विधियों को बदलें ताकि वे शून्य न लौटें या चेनिंग विधियों से बचें जो शून्य को वापस कर सकते हैं।

5

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

ऐसे अन्य विकल्प भी हैं जिन्हें आपने यहां नहीं माना है। a(), b(), इत्यादि होने के बजाय त्रुटि को सिग्नल करने के लिए null लौटाएं, उन्हें अधिक विस्तृत अपवाद फेंकने पर विचार करें कि वे कुछ वापस क्यों नहीं कर सकते हैं। यदि वे विफल हो रहे हैं क्योंकि नेटवर्क कनेक्शन ड्रॉप है, तो उन्हें IOException एस या कुछ पसंद करें। यदि वे असफल हो रहे हैं क्योंकि आपके पास सरणी में एक खराब अनुक्रमणिका है, तो यह भी स्पष्ट करें।

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

5

आम तौर पर, कोड की यह पंक्ति शून्य समस्या को अनदेखा कर स्वयं ही खराब होगी। "Law of Demeter" or "Principle of Least Knowledge" देखें।

return a().b().c().d().e(); 

यदि मेरे पास ए, बी, सी, डी, और ई पर कोई नियंत्रण नहीं था, तो मैं निम्नलिखित को फिर से लिखूंगा।

if((a()!=null) && (a().b() != null) && ....) { 
    return a().b().c().d().e(); 
} else { 
    return null; 
} 

इस के रूप में, जो अभी भी जघन्य है लेकिन कुछ गड़बड़ होने पर मुझे और अधिक उपयोगी तरीका है और मुझे एक स्टैक ट्रेस पढ़ने की जरूरत है।

B b = a.a(); 
if(b == null) 
{ 
    return null; 
} 

C c = b.b(); 
if(c == null) 
{ 
    return null; 
} 

D d = c.c(); 
if(d == null) 
{ 
    return null; 
} 

return d.d(); 

नहीं, NullPointerException को पकड़ना उचित बात नहीं है। ArrayIndexOutOfBoundsException को पकड़ने के लिए try ब्लॉक में for लूप को लपेटने की तरह है।

यदि यह fluent API होना चाहिए जहां चेनिंग एक ताकत और लक्ष्य है तो इसे कभी भी नल वापस नहीं करना चाहिए।

+1

मैं आम तौर पर सहमत हूं, लेकिन आपके पास हमेशा कोई विकल्प नहीं है, उदा। तीसरे पक्ष पुस्तकालयों का उपयोग करते समय। एक और मामला जहां यह ऑब्जेक्ट - रिलेशन डीबी मैपिंग्स में बहुत कुछ हो सकता है, उदाहरण: resultSet.getFirst()। GetPerson()। GetBusinessUnit()। GetAddress()। GetPostCode(); यदि डीबी स्कीमा बहुत आंशिक जानकारी की अनुमति देता है तो यह मामला बहुत कुछ हो सकता है। Arrayindexoutofbounds तुलना के लिए – Carsten

+0

+1, यह स्थान पर है। – Epaga

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