2013-05-07 10 views
23

मैंने देखा कि Java 7 में, उन्होंने विधि Objects.requireNonNull(T obj, String message) पेश की।जावा 7 कन्स्ट्रक्टर

चेकों कि निर्दिष्ट ऑब्जेक्ट संदर्भ रिक्त नहीं है और एक अनुकूलित NullPointerException अगर यह होता है फेंकता है। यह विधि कई पैरामीटर के साथ विधियों और कन्स्ट्रक्टर में पैरामीटर सत्यापन करने के लिए मुख्य रूप से डिज़ाइन की गई है।

मेरे कोड को दोबारा सुधारने से पहले, मैं यहां उपयोग करने के बारे में कुछ प्रतिक्रिया देने के लिए कहूंगा।

public Foo(Bar bar, Baz baz) { 
     /** Old one 
     this.bar = bar; 
     this.baz = baz; 
     **/ 
     this.bar = Objects.requireNonNull(bar, "bar must not be null"); 
     this.baz = Objects.requireNonNull(baz, "baz must not be null"); 
    } 

यह एक बेहतर अभ्यास सीधे इसका इस्तेमाल करने की जब मैं अपने वस्तु (मैं के बारे में सोच रहा था कि अगर मैं डेवलपर्स के लिए एक पुस्तकालय या अन्य सामग्री बनाने) का निर्माण है?

या मुझे इसे "क्लासिक/पुराना एक" कन्स्ट्रक्टर के रूप में छोड़ देना चाहिए?

+0

यह निर्भर करता है। क्या आप अपने कन्स्ट्रक्टर में एक अपवाद फेंकना चाहते हैं? – Reimeus

+0

दरअसल, अगर निर्माता को अपवाद नहीं दिया जाता है, तो निश्चित रूप से इस वर्ग के तरीकों को बुलाकर इसे फेंक दिया जाएगा। इसका उद्देश्य यह है: क्या मुझे सीधे निर्माण पर उपयोगकर्ता को रोकना चाहिए ("सावधान रहें कि कुछ ऑब्जेक्ट्स शून्य हैं इसलिए आप कुछ तरीकों को करने में सक्षम नहीं होंगे") या क्या मैं उन्हें इस अपवाद को फेंकने देता हूं (अगर वह कॉल करता है कक्षा के कुछ तरीकों)? – user2336315

+0

मैं यहाँ बिल्डर पद्धति का उपयोग कर के लिए ले जाया गया है, और, रवि नीचे से पता चलता है के रूप में, IllegalArgumentException फेंक (या IllegalStateException।) – Marvo

उत्तर

11

जैसा कि आप देख सकते हैं, असहमति है कि एनपीई या कुछ अन्य अपवाद फेंक दिया जाना चाहिए।

आप स्वीकार करते हैं कि एक एनपीई विकल्पों से अधिक उपयुक्त है, और यह एक स्थिति है जहाँ null स्पष्ट गलत है, तो यह है:

  • यह एनपीई जल्दी फेंक करने के लिए बेहतर है, यानी कन्स्ट्रक्टर में, और
  • इसे कस्टम अपवाद संदेश के साथ फेंकना बेहतर है; यानी null ऐसा नहीं होता है जब JVM एनपीई फेंकता है।

Objects.requireNonNull का उपयोग कर उस संदर्भ में स्पष्ट रूप से अच्छा अभ्यास है।


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

(थ्रेडिंग-संबंधित बग अक्सर "नीले चंद्रमा में एक बार" चीजें होती हैं जो पुन: पेश करने में बहुत मुश्किल होती हैं। मैं तर्क दूंगा कि समस्या का निदान करने के लिए आपको जानकारी की आवश्यकता होती है जब भी ऐसा होता है ... न केवल जब आप assertion जांच सक्षम है।)


पिछड़ा संगतता तर्क संभवतः प्रासंगिक है। हालांकि, एक सामान्य नियम के रूप में आप पुराने जावा प्लेटफ़ॉर्म पर चलाने के लिए अपना कोड लिखें। यदि आपके पास जावा के पुराने संस्करणों का समर्थन करने के लिए विशिष्ट आवश्यकता है ... यह अलग है। लेकिन अगर ऐसा होता है, तो आपको जावा 7 एपीआई के खिलाफ अपना विकास नहीं करना चाहिए ... इसलिए आपके कंपाइलर/आईडीई को संकलन त्रुटि के रूप में Objects कक्षा को ध्वजांकित करना चाहिए।

(केवल पुराने एपीआई का उपयोग करने के लिए खुद को प्रतिबंधित करना जब आपको अपनी कोड गुणवत्ता को पीड़ित करने की आवश्यकता नहीं होती है, और इसे पहले से "पुराना" बना दिया जाता है। नई सामग्री के इसे बनाना है आसान विश्वसनीय/पोषणीय अनुप्रयोगों लिखने के लिए जानबूझ कर का उपयोग नहीं यह है ... विकृत कल्पना कीजिए यदि आप अपने आप को जावा 1.1 तक ही सीमित ...)


1 -।। Fwiw, मुझे लगता है कि एनपीई के ठीक कर रहे हैं। और संदेश के साथ एनपीई (कहें) IllegalArgumentException से अधिक विशिष्ट है, और रचनाकारों के लिए जावा मानक वर्ग पुस्तकालयों में बहुत से उदाहरण हैं, जो दस्तावेज एनपीई फेंकने के रूप में दस्तावेज हैं। इसके अलावा, इस विधि को इस तरह इस्तेमाल करने के लिए स्पष्ट रूप से डिजाइन किया गया था।

+0

+1 .. और जैसा कि मैंने @Ravi से कहा .. भी लगता है एनपीई बेहतर (अधिक विशिष्ट) IllegalArgumentException (या IStateExc) – joaonlima

+0

से है 'यह आपके सिस्टम नीचे (अन्य दावे की जांच के बहुत सारे के कारण) धीमा कर देगा?' नहीं, क्योंकि आप उदाहरण के लिए केवल एक पैकेज के लिए चुनिंदा रूप से दावा सक्षम कर सकते हैं। –

+0

@Ravi - केवल अगर आपको पता है कि कौन सा पैकेज उस वर्ग में है जिसमें 'assert' है जो समस्या को पकड़ लेगा। और फिर भी, कक्षा/पैकेज/जो कुछ भी आपने चुनिंदा रूप से सक्षम किए गए हैं, में अन्य ** अधिक महंगा ** 'जोर' चेक हो सकते हैं। –

0

आप bar और baz के लिए setters के लिए है, तो आप setters में यह करना चाहिए:

public Foo(Bar bar, Baz baz) { 
    setBar(bar); 
    setBaz(baz); 
} 

public void setBar(Bar bar) { 
    this.bar = Objects.requireNonNull(bar, "bar must not be null"); 
} 

public void setBaz(Baz baz) { 
    this.baz = Objects.requireNonNull(baz, "baz must not be null"); 
} 

अन्यथा विधि आप से पता चला है ठीक है।

बिल्कुल यह करने के बारे में सवाल के बारे में - अगर आपके वस्तु पूरी तरह से बेकार जब bar और baz अशक्त हो रहा है, तो आप के रूप में अच्छी अशक्त जांच निर्माता & setters पर कर सकता है। लेकिन यदि आपकी ऑब्जेक्ट का उपयोग तब किया जा सकता है जब वे शून्य होते हैं - भले ही वह उपयोग सिर्फ यह जांच रहा हो कि वे शून्य हैं और उन्हें एक सेटटर के साथ सेट कर रहे हैं, यह मानते हुए कि यह आपकी कक्षा का वैध उपयोग है - तो आप अपने उपयोगकर्ताओं को ऐसा करने दे सकते हैं।

9

मुझे इस तथ्य से सहज महसूस नहीं होता है कि requireNonNull()NullPointerException फेंकता है। मेरी राय में, क्लासिक IllegalArgumentException फेंकने से इरादा अधिक स्पष्ट हो जाता है। कोई Assertions का उपयोग कर सकते हैं साथ ही लाभ के साथ कि उन्हें चुनिंदा रूप से चालू और बंद किया जा सकता है।

इसके शीर्ष पर, यदि आप लाइब्रेरी के रूप में अपना कोड बेनकाब करना चाहते हैं तो आमतौर पर सबसे पुराना जेडीके का समर्थन करने का प्रयास करें।

EDIT: मैं यह जोड़ना चाहता हूं कि आज कोई ज्ञात ढांचा चुनें और आप पाएंगे कि उनके एपीआई हमेशा नामों के साथ अपवाद फेंक देंगे ताकि आप लगभग तुरंत जान सकें कि क्या गलत है।

उदाहरण देने के लिए, क्या होता है जब एक स्प्रिंग कंटेनर को पता चलता है कि एक प्रबंधित बीन पर @Required संपत्ति इंजेक्शन नहीं दी जा सकती है और इसलिए NULL बना हुआ है। आपको निश्चित रूप से NullPointerException प्राप्त नहीं होता है जितना संभव हो सके एक त्रुटि संदेश वर्णनात्मक।

आप एक BeanCreationException एक BeanInitializationException सदस्य चर अब भी है कि जैसे एक वर्णनात्मक पर्याप्त त्रुटि संदेश में null बारे में अधिक जानकारी देने के चारों ओर लिपटा मिलती है: संपत्ति 'केंद्र' सेम 'चक्र' के लिए आवश्यक है।

+0

मैं सहमत नहीं .. NullPointerException, मेरी राय में, इस मामले में अधिक उपयुक्त है क्योंकि यह स्पष्ट रूप से कहा गया है समस्या एक 'null' पारित किया जा रहा है जहां यह नहीं हो सकता है कि (हम एक संदेश है के बाद से)। एक IllegalArgument कुछ भी गलत द्वारा उत्पादित किया जा सकता है, Argumento 0 से अधिक होना चाहिए, मूल्य serializable, आदि होना चाहिए – joaonlima

+1

हाँ, यह वरीयता के एक छोटा सा नीचे उबाल है। लेकिन, व्यक्तिगत रूप से मुझे नहीं लगता कि मेरा लाइब्रेरी कोड अधिक आत्मविश्वास उत्पन्न करेगा यदि यह NullPointerExceptions को फेंकना शुरू कर देता है। डिफ़ॉल्ट अर्थशास्त्र जो किसी भी जावा प्रोग्रामर के साथ संबद्ध है यह है कि कोड में एक बग है; *कुछ टूटा है*। मैं इससे जितना संभव हो उतना दूर रहना चाहता हूं। –

+2

@Ravi - मानक संग्रह वर्गों में से कई लोग, जब 'null' तर्कों के साथ कॉल NPEs उत्पन्न ही कई अन्य मानक वर्गों है। क्या यह आपको >>< कम आत्मविश्वास महसूस करता है? बेशक, बग्गी कोड अक्सर एनपीई पैदा करता है, लेकिन रिवर्स अनुमान बनाने के लिए यह तर्कसंगत नहीं है ... विशेष रूप से यदि आप * दस्तावेज * जिन परिस्थितियों में एनपीई की अपेक्षा की जा सकती है। अगर कोई मानता है कि एक एनपीई का मतलब है कि आपका कोड छोटी है, तो वे बेवकूफ़ हैं। –