जावा में चेक को शून्य किए बिना मान प्राप्त करना


15

जब मैं NullPointerException से बचने के लिए कुछ डेटा पदानुक्रम से मान प्राप्त कर रहा हूं, तो कई बार मैं अपने आप को शून्य जांच पाता हूं, जो मुझे त्रुटियों और बहुत अधिक बॉयलरप्लेट की आवश्यकता के कारण लगता है।

मैंने एक बहुत ही सरल दिनचर्या लिखी है जो मुझे किसी वस्तु को लाते समय अशक्त जाँच को छोड़ देती है ...

public final class NoNPE {

    public static <T> T get(NoNPEInterface<T> in) {
        try {
            return in.get();
        } catch (NullPointerException e) {
            return null;
        }
    }

    public interface NoNPEInterface<T> {
        T get();
    }
}

मैं इसे इस तरह से उपयोग करता हूं ...

Room room = NoNPE.get(() -> country.getTown().getHouses().get(0).getLivingRoom());

उपरोक्त के परिणामस्वरूप मुझे सभी मूल स्तरों की जांच करने के लिए बिना एक कक्ष ऑब्जेक्ट या नल मिल रहा है।

आप ऊपर वाले से क्या समझते हैं? क्या मैं एक समस्याग्रस्त पैटर्न बना रहा हूँ? क्या आपकी राय में ऐसा करने का कोई बेहतर तरीका है?


1
जैसा कि आप जाहिरा तौर पर जावा 8 का उपयोग कर रहे हैं, क्या मैं आपको सुझाव दे सकता हूं कि आप java.util.Optionalलापता डेटा का प्रतिनिधित्व करने के लिए नल के बजाय अपने आवेदन को नया स्वरूप देने पर विचार करें ? यह आपके द्वारा वर्णित केस और उन मामलों के लिए उपयोगी उपयोगिताओं को प्रदान करता है, जहां आप चेन के अंत में विफलता की स्थिति में लौटने के बजाय डिफ़ॉल्ट डेटा के साथ ले जाना चाहते हैं ..
Periata Breatta

मुझे लगता है कि आपने अनिवार्य रूप से Option(या Maybe) मोनद :) को फिर से खोज लिया है :)
एंड्रेस एफ।

टी या नल के बजाय वैकल्पिक लौटना संभव हो सकता है: इस तरह आप सीधे ऑर्ल () विधि का उपयोग कर सकते हैं। 18 महीने बाद, लेकिन किसी की मदद कर सकता है।
बेंज अग्ली

इस पोस्ट में एक और दृष्टिकोण का उल्लेख किया गया है गैरकानूनी रूप से मान्यता। blogspot.com/2015/03/… , उनमें से एक kludje नामक एक पुस्तकालय का उपयोग कर रहा है जिसमें एक बहुत ही दिलचस्प वाक्यविन्यास है
बेंज

जवाबों:


13

आपका समाधान बहुत स्मार्ट है। मुझे जो समस्या दिखाई दे रही है वह यह है कि आप नहीं जानते कि आपको ए क्यों मिला है null? क्या इसलिए कि घर में कमरे नहीं थे? क्या यह वजह थी कि शहर में कोई घर नहीं था? क्या इसलिए कि देश का कोई कस्बा नहीं था? क्या ऐसा इसलिए था nullक्योंकि संग्रह में 0 की स्थिति में एक त्रुटि होने के कारण भी स्थिति 1 और अधिक से अधिक थी?

यदि आप NonPEकक्षा का विस्तार से उपयोग करते हैं , तो आपको गंभीर डिबगिंग समस्याएं होंगी। मुझे लगता है कि यह जानना बेहतर है कि वास्तव में चेन कहां से टूटी है चुपचाप पाने के लिए nullजो एक गहरी त्रुटि को छिपा सकता है।

इसके अलावा इस का उल्लंघन करती है Demeter के कानून : country.getTown().getHouses().get(0).getLivingRoom()। अधिक बार नहीं, कुछ अच्छे सिद्धांत का उल्लंघन करने से आपको इस तरह के सिद्धांत का उल्लंघन करने के कारण होने वाली समस्या को हल करने के लिए अपरंपरागत समाधान लागू करना पड़ता है।

मेरी सिफारिश है कि आप इसे सावधानी के साथ उपयोग करें और डिजाइन दोष को हल करने का प्रयास करें जो आपको ट्रेन के मलबे एंटिप्टर्न में उकसाना है (ताकि आपको NonPEहर जगह उपयोग न करना पड़े )। अन्यथा आपके पास ऐसे कीड़े हो सकते हैं जिनका पता लगाना मुश्किल होगा।


बहुत बढ़िया जवाब। हां, मुझे नहीं पता होगा कि मुझे श्रृंखला में अशक्त कहां मिला है। कई मामलों में, हालांकि मुझे परवाह नहीं है और चेक न करने का मतलब है कि कोड अधिक पठनीय है और बॉयलरप्लेट त्रुटि के लिए कम संभावना है। लेकिन हाँ आप कुछ मामलों में सही हैं जहाँ मुझे एक अलग तार्किक निर्णय लेने की आवश्यकता है यदि कोई मूल वस्तु अशक्त है, तो यह एक समस्या का कारण होगा। पारंपरिक विधि या वैकल्पिक वर्ग वहाँ एक सुरक्षित समाधान हो सकता है।
यूरिग जोन्स

सामान्य तौर पर, जब Optionमोनाड का उपयोग करते हैं , तो आपको परवाह नहीं है कि श्रृंखला में अनुपस्थित मूल्य कहां है। जब आप इसके बारे में परवाह करते हैं, तो आप शायद एक अलग प्रकार का उपयोग करेंगे, जैसे कि Either
एंड्रेस एफ।

ओपी का दृष्टिकोण सी # 6 ?.और ?[]ऑपरेटरों के समान है । जब आप ऐसी चीज़ का उपयोग करना चाहते हैं, तो इसका एक उदाहरण पदानुक्रमित सर्वर-साइड सेटिंग्स है। var shouldDoThing = settings?.a?.b?.c ?? defaultSetting;कौन परवाह करता है कि उस का कोई हिस्सा क्यों अशक्त था? शायद आप सेटिंग नहीं ला सकते। हो सकता है कि आपने सेटिंग्स के एक हिस्से को हटाने का फैसला किया हो। किसी भी स्थिति में, आप वास्तव में सर्वर की सेटिंग्स प्राप्त करने पर भरोसा नहीं कर सकते हैं, इसलिए एक डिफ़ॉल्ट आमतौर पर एक अच्छा विचार है, और आपको परवाह नहीं है कि आप वास्तविक सेटिंग क्यों नहीं प्राप्त कर सकते हैं जब तक कि यह बहुत बार नहीं होना चाहिए। ।
क्रिस

अब मैं यह नहीं कह रहा हूं कि चूक को स्थानीय बनाने की तुलना में कड़ाई से बेहतर या बदतर है और सामान्य पहुंच के माध्यम से आप जो मूल्य चाहते हैं उसे वापस पा सकते हैं settings.a.b.c। तो फिर, यह एक एकल पृथक उदाहरण है।
क्रिस

10

विचार ठीक है, वास्तव में अच्छा है। चूंकि जावा 8 Optionalप्रकार मौजूद हैं, इसलिए जावा वैकल्पिक प्रकार पर एक विस्तृत विवरण पाया जा सकता है । आपके द्वारा पोस्ट किया गया एक उदाहरण है

Optional.ofNullable(country)
    .map(Country::getTown)
    .map(Town::Houses);

और आगे।


1
हां, मैं वैकल्पिक कक्षा जावा 8 और अमरूद दोनों से वाकिफ था और वे वास्तव में उपयोगी हैं। लेकिन आप सिर्फ एक वस्तु नहीं ला सकते हैं क्योंकि आप सामान्य रूप से कोड को पढ़ने के लिए थोड़ा कठिन बना देंगे और थोड़ा कम प्रदर्शन भी करेंगे। लेकिन उल्टा यह है कि कई बहुत उपयोगी ऑपरेटर हैं जो वैकल्पिक वर्ग प्रदान करता है।
यूरिग जोन्स

3
@EurigJones मुझे नहीं लगता कि कोड कम प्रदर्शनकारी हो जाता है। देखने वाले की नज़र में पठनीयता, लेकिन मेरा तर्क Optionalहै कि दो का अधिक पठनीय समाधान है, यदि केवल इसलिए - क्योंकि आपके प्रस्ताव के विपरीत - यह एक बहुत ही सामान्य मुहावरा है। यह तुम्हारी तुलना में भी अधिक संक्षिप्त है!
एंड्रेस एफ।

0

आपका तरीका अपने इच्छित उद्देश्य के लिए पर्याप्त रूप से काम करता है, हालांकि nullजब आपको NullPointerExceptionखराब डिज़ाइन जैसी आवाज़ मिलती है तो वापस लौटता है ।

nullएस से बचने की कोशिश करें जब आप कर सकते हैं और केवल उन्हें पास कर सकते हैं जब वे किसी चीज़ का प्रतिनिधित्व करते हैं या उनका विशेष अर्थ होता है और केवल उन्हें वापस करते हैं जब वे प्रतिनिधित्व करते हैं / कुछ का मतलब करते हैं - अन्यथा आपको ए फेंकना चाहिए NullPointerException। यह कीड़े और भ्रम से बचा जाता है। यदि Objectनहीं होना चाहिए null, NullPointerतो फेंक दिया जाना चाहिए। यदि कोई वस्तु हो सकती है, nullतो किसी के पास जाने पर कुछ भी गलत नहीं होगा। अन्यथा आपकी विधि ऊपर काम करती है।


0

मैं आपका दर्द महसूस कर सकता हूं, लेकिन प्रस्तावित समाधान एक बुरा विचार है।

  • यदि कोई अन्य किसी कारण से एनपीई फेंकता है, तो आप इसे अनदेखा कर देंगे।
  • उस आंतरिक मेमने के लिए एक भयानक कोड में बढ़ने का जोखिम है। उदाहरण के लिए, यदि शहर में कोई घर नहीं है, तो एक विशेष स्थिरांक वापस करने की एक नई आवश्यकता है, एक आलसी प्रोग्रामर लैमडा का विस्तार कर सकता है, जिसमें सब कुछ लपेटा जा सकता है NoNPE.get
  • जैसा कि पहले ही उल्लेख किया गया है, Optional.mapवह है जो आप खोज रहे हैं।
  • NullPointerException का एक नया उदाहरण बनाने का दंड अक्सर महत्वपूर्ण होता है। यह कई माइक्रोसेकंड है, विशेष रूप से आपके कॉल स्टैक के रूप में बड़ा हो रहा है। यह अनुमान लगाना कठिन है कि आपकी उपयोगिता कहां समाप्त होगी।

एक साइड नोट के रूप में, NoNPEInterfaceएक डुप्लिकेट है java.util.function.Supplier

कुछ मामलों में आप एक अभिव्यक्ति मूल्यांकन बर्तन का उपयोग करने पर विचार कर सकते हैं जो कई रूपरेखाओं में मौजूद हैं (उदाहरण के लिए: ईएल, स्पेल):

evaluateProperty(country, "town.houses[0].livingRoom")

वेब पेज टेम्प्लेट के लिए ठीक है, लेकिन आम तौर पर विकसित करने के लिए धीमा (कोई संकलन समय की जाँच नहीं) और चलाने के लिए धीमा।
केविन क्लाइन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.