java बचना! = शून्य बयान




15 Answers

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

असल में, आपको @Nullable और @Nullable मिल गया है।

आप विधि और पैरामीटर में इस तरह उपयोग कर सकते हैं:

@NotNull public static String helloWorld() {
    return "Hello World";
}

या

@Nullable public static String helloWorld() {
    return "Hello World";
}

दूसरा उदाहरण संकलित नहीं होगा (इंटेलिजे आईडीईए में)।

जब आप कोड के दूसरे भाग में पहले helloWorld() फ़ंक्शन का उपयोग करते हैं:

public static void main(String[] args)
{
    String result = helloWorld();
    if(result != null) {
        System.out.println(result);
    }
}

अब इंटेलिजे आईडीईए कंपाइलर आपको बताएगा कि चेक बेकार है, क्योंकि helloWorld() फ़ंक्शन null वापस नहीं लौटाएगा।

पैरामीटर का उपयोग करना

void someMethod(@NotNull someParameter) { }

यदि आप कुछ लिखते हैं:

someMethod(null);

यह संकलित नहीं होगा।

@Nullable का उपयोग कर अंतिम उदाहरण

@Nullable iWantToDestroyEverything() { return null; }

यह कर रहा हूं

iWantToDestroyEverything().something();

और आप सुनिश्चित हो सकते हैं कि ऐसा नहीं होगा। :)

यह एक अच्छा तरीका है कि कंपाइलर आमतौर पर ऐसा कुछ करने की जांच करता है और आपके अनुबंधों को मजबूत बनाने के लिए लागू करता है। दुर्भाग्यवश, यह सभी कंपाइलरों द्वारा समर्थित नहीं है।

IntelliJ IDEA 10.5 और बाद में, उन्होंने किसी भी अन्य @Nullable कार्यान्वयन के लिए समर्थन जोड़ा।

ब्लॉग पोस्ट देखें अधिक लचीला और कॉन्फ़िगर करने योग्य @ Nullable / @ NotNull एनोटेशन

java object nullpointerexception null

मैं object != null उपयोग करता हूं object != null NullPointerException से बचने के लिए बहुत कुछ नहीं।

क्या इसका कोई अच्छा विकल्प है?

उदाहरण के लिए:

if (someobject != null) {
    someobject.doCalc();
}

यह एक NullPointerException से बचाता है, जब यह अज्ञात है यदि ऑब्जेक्ट null या नहीं।

ध्यान दें कि स्वीकृत उत्तर पुराना हो सकता है, अधिक हालिया दृष्टिकोण के लिए https://.com/a/2386013/12943 देखें।




वाह, जब हम NullObject pattern की सिफारिश करने के 57 अलग-अलग तरीके हैं, तो मुझे लगभग एक और जवाब जोड़ने से नफरत है, लेकिन मुझे लगता है कि इस प्रश्न में रुचि रखने वाले कुछ लोग यह जानना चाहेंगे कि जावा 7 के लिए टेबल पर एक प्रस्ताव है "शून्य -साफ हैंडलिंग " - एक सुव्यवस्थित वाक्यविन्यास अगर-बराबर-शून्य तर्क के लिए।

एलेक्स मिलर द्वारा दिया गया उदाहरण इस तरह दिखता है:

public String getPostcode(Person person) {  
  return person?.getAddress()?.getPostcode();  
}  

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

अद्यतन: जावा 7 में एक नल-सुरक्षित ऑपरेटर के लिए एक proposed परियोजना सिक्का के तहत प्रस्तुत किया गया है वाक्यविन्यास ऊपर दिए गए उदाहरण से थोड़ा अलग है, लेकिन यह वही धारणा है।

अद्यतन: शून्य-सुरक्षित ऑपरेटर प्रस्ताव ने इसे परियोजना सिक्का में नहीं बनाया है। तो, आप जावा 7 में यह वाक्यविन्यास नहीं देख पाएंगे।




केवल इस स्थिति के लिए -

एक बराबर विधि का आह्वान करने से पहले एक चर शून्य है या नहीं, यह जांच नहीं कर रहा है (एक स्ट्रिंग नीचे उदाहरण की तुलना करें):

if ( foo.equals("bar") ) {
 // ...
}

अगर foo मौजूद नहीं है तो परिणामस्वरूप NullPointerException होगा।

यदि आप अपनी String तुलना इस तरह करते हैं तो आप इससे बच सकते हैं:

if ( "bar".equals(foo) ) {
 // ...
}



आप किस प्रकार की ऑब्जेक्ट्स की जांच कर रहे हैं, इस पर निर्भर करते हुए आप अपाचे कॉमन्स में कुछ कक्षाओं का उपयोग करने में सक्षम हो सकते हैं जैसे: apache commons lang और apache commons संग्रह

उदाहरण:

String foo;
...
if( StringUtils.isBlank( foo ) ) {
   ///do something
}

या (आपको जो जांचने की आवश्यकता है उसके आधार पर):

String foo;
...
if( StringUtils.isEmpty( foo ) ) {
   ///do something
}

स्ट्रिंगउल्ट्स क्लास केवल कई में से एक है; उन कॉमन्स में बहुत अच्छी कक्षाएं हैं जो शून्य सुरक्षित हेरफेर करते हैं।

जब आप अपाचे लाइब्रेरी (कॉमन्स-लैंग-2.4.jar) शामिल करते हैं तो आप जावा में शून्य वर्लीकरण का उपयोग कैसे कर सकते हैं इसका एक उदाहरण यहां दिया गया है।

public DOCUMENT read(String xml, ValidationEventHandler validationEventHandler) {
    Validate.notNull(validationEventHandler,"ValidationHandler not Injected");
    return read(new StringReader(xml), true, validationEventHandler);
}

और यदि आप वसंत का उपयोग कर रहे हैं, तो वसंत में भी इसके पैकेज में समान कार्यक्षमता है, लाइब्रेरी देखें (वसंत-2.4.6.jar)

वसंत से इस स्थिर वर्ग का उपयोग करने के तरीके पर उदाहरण (org.springframework.util.Assert)

Assert.notNull(validationEventHandler,"ValidationHandler not Injected");



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




कभी-कभी, आपके पास ऐसे पैरामीटर होते हैं जो इसके पैरामीटर पर काम करते हैं जो एक सममित ऑपरेशन को परिभाषित करते हैं:

a.f(b); <-> b.f(a);

यदि आप जानते हैं कि बी कभी भी शून्य नहीं हो सकता है, तो आप इसे स्वैप कर सकते हैं। यह बराबर के लिए सबसे उपयोगी है: foo.equals("bar"); बजाय foo.equals("bar"); बेहतर करें "bar".equals(foo);




जावा 7 में एक नई java.util.Objectsउपयोगिता कक्षा है जिस पर एक requireNonNull()विधि है। NullPointerExceptionयदि यह तर्क शून्य है, तो यह सब फेंक दिया जाता है, लेकिन यह कोड को थोड़ा सा साफ़ करता है। उदाहरण:

Objects.requireNonNull(someObject);
someObject.doCalc();

यह विधि किसी कन्स्ट्रक्टर में असाइनमेंट से पहले checking लिए सबसे उपयोगी है , जहां इसका प्रत्येक उपयोग कोड की तीन पंक्तियों को बचा सकता है:

Parent(Child child) {
   if (child == null) {
      throw new NullPointerException("child");
   }
   this.child = child;
}

हो जाता है

Parent(Child child) {
   this.child = Objects.requireNonNull(child, "child");
}



आखिरकार, इस समस्या को पूरी तरह हल करने का एकमात्र तरीका एक अलग प्रोग्रामिंग भाषा का उपयोग करना है:

  • उद्देश्य-सी में, आप एक विधि का आह्वान करने के बराबर कर सकते हैं nil , और बिल्कुल कुछ भी नहीं होगा। इससे सबसे अधिक शून्य अनावश्यक जांच करता है, लेकिन यह निदान के लिए त्रुटियों को अधिक कठिन बना सकता है।
  • में Nice एक संभावित-अशक्त संस्करण और एक नहीं अशक्त संस्करण:, एक जावा व्युत्पन्न भाषा, वहाँ सभी प्रकार के दो संस्करणों रहे हैं। आप केवल नल प्रकारों पर विधियों का आह्वान कर सकते हैं। संभावित रूप से शून्य प्रकारों को शून्य के लिए स्पष्ट जांच के माध्यम से गैर-शून्य प्रकारों में परिवर्तित किया जा सकता है। इससे यह जानना बहुत आसान हो जाता है कि शून्य चेक आवश्यक हैं और जहां वे नहीं हैं।



यह पूछकर कि सवाल बताता है कि आपको त्रुटि प्रबंधन रणनीतियों में रुचि हो सकती है। आपकी टीम के आर्किटेक्ट को यह तय करना चाहिए कि त्रुटियों को कैसे काम करना है। इसे करने बहुत सारे तरीके हैं:

  1. अपवादों को घुमाने के लिए अनुमति दें - उन्हें 'मुख्य पाश' या किसी अन्य प्रबंधन दिनचर्या में पकड़ें।

    • त्रुटि की स्थिति की जांच करें और उन्हें उचित रूप से संभाल लें

निश्चित रूप से आस्पेक्ट ओरिएंटेड प्रोग्रामिंग पर भी एक नज़र डालें, उनके पास if( o == null ) handleNull()आपके बाइटकोड में डालने के साफ-सुथरे तरीके हैं ।




बस शून्य का उपयोग न करें। इसे अनुमति न दें।

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

एक बार मैंने इस अभ्यास को अपनाया, मैंने देखा कि समस्याएं खुद को ठीक करने लगती हैं। आप केवल दुर्घटना से विकास प्रक्रिया में चीजों को पकड़ लेंगे और महसूस करेंगे कि आपके पास कमजोर जगह थी .. और सबसे महत्वपूर्ण बात यह है कि यह विभिन्न मॉड्यूल की चिंताओं को समाहित करने में मदद करता है, विभिन्न मॉड्यूल एक-दूसरे पर भरोसा कर सकते हैं, और अब और कूड़ेदान नहीं कर सकते के साथ कोडif = null else संरचना !

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

class C {
    private final MyType mustBeSet;
    public C(MyType mything) {
       mustBeSet=Contract.notNull(mything);
    }
   private String name = "<unknown>";
   public void setName(String s) {
      name = Contract.notNull(s);
   }
}


class Contract {
    public static <T> T notNull(T t) { if (t == null) { throw new ContractException("argument must be non-null"); return t; }
}

अनुबंध मिनी-यूनिट परीक्षणों की तरह हैं जो हमेशा उत्पादन में होते हैं, और जब चीजें असफल होती हैं, तो आप जानते हैं कि क्यों एक यादृच्छिक एनपीई के बजाय आपको किसी भी तरह का पता लगाना है।




यह हर जावा डेवलपर के लिए एक बहुत ही आम समस्या है। इसलिए बिना किसी अव्यवस्थित कोड के इन मुद्दों को हल करने के लिए जावा 8 में आधिकारिक समर्थन है।

जावा 8 पेश किया गया है java.util.Optional<T>। यह एक कंटेनर है जो गैर-शून्य मान रख सकता है या नहीं। जावा 8 ने किसी ऑब्जेक्ट को संभालने का एक सुरक्षित तरीका दिया है जिसका मूल्य कुछ मामलों में शून्य हो सकता है। यह Haskell और Scala के विचारों से प्रेरित हैScala

संक्षेप में, वैकल्पिक वर्ग में ऐसे मामलों से स्पष्ट रूप से निपटने के तरीके शामिल हैं जहां मूल्य मौजूद है या अनुपस्थित है। हालांकि, शून्य संदर्भों की तुलना में लाभ यह है कि वैकल्पिक <टी> वर्ग आपको उस मामले के बारे में सोचने के लिए मजबूर करता है जब मान मौजूद नहीं होता है। नतीजतन, आप अनपेक्षित शून्य सूचक अपवादों को रोक सकते हैं।

उपरोक्त उदाहरण में हमारे पास एक घरेलू सेवा कारखाना है जो घर में उपलब्ध कई उपकरणों के लिए एक हैंडल देता है। लेकिन ये सेवाएं उपलब्ध / कार्यात्मक नहीं हो सकती हैं या नहीं; इसका मतलब है कि इसका परिणाम नलपॉन्टर अपवाद में हो सकता है। ifकिसी भी सेवा का उपयोग करने से पहले एक शून्य स्थिति जोड़ने के बजाय , इसे वैकल्पिक <सेवा> में लपेटें।

विकल्प के लिए लपेटना <टी>

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

public Optional<Service> getRefrigertorControl() {
      Service s = new  RefrigeratorService();
       //...
      return Optional.ofNullable(s);
   }

जैसा कि आप देखते हैं Optional.ofNullable()संदर्भ लपेटने के लिए एक आसान तरीका प्रदान करता है। वैकल्पिक के संदर्भ प्राप्त करने के अन्य तरीके हैं, या तो Optional.empty()&Optional.of() । एक नल को फिर से चालू करने के बजाय एक खाली वस्तु को वापस करने के लिए और दूसरे को क्रमशः एक गैर-शून्य वस्तु को लपेटने के लिए।

तो वास्तव में यह एक पूर्ण जांच से बचने के लिए कैसे मदद करता है?

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

Optional ref = homeServices.getRefrigertorControl();
ref.ifPresent(HomeServices::switchItOn);

वैकल्पिक .ifPresent किसी दिए गए उपभोक्ता को एक संदर्भ के साथ आमंत्रित करता है यदि यह एक गैर-शून्य मान है। अन्यथा, यह कुछ भी नहीं करता है।

@FunctionalInterface
public interface Consumer<T>

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

हम निरंतर स्थिति की जांच के लिए अक्सर एक वैकल्पिक मूल्य या डिफ़ॉल्ट मान वापस करने के लिए टर्नरी ऑपरेटर का उपयोग करते हैं। वैकल्पिक बिना किसी जांच के एक ही स्थिति को संभालने का एक और तरीका प्रदान करता है। वैकल्पिक .orElse (defaultObj) डिफ़ॉल्ट ओबीजे देता है यदि वैकल्पिक के पास शून्य मान होता है। आइए इसका इस्तेमाल हमारे नमूना कोड में करें:

public static Optional<HomeServices> get() {
    service = Optional.of(service.orElse(new HomeServices()));
    return service;
}

अब HomeServices.get () एक ही चीज़ करता है, लेकिन एक बेहतर तरीके से। यह जांचता है कि सेवा पहले ही शुरू नहीं हुई है या नहीं। यदि यह वही है तो उसे वापस करें या एक नई नई सेवा बनाएं। वैकल्पिक <टी> .orElse (टी) एक डिफ़ॉल्ट मान वापस करने में मदद करता है।

अंत में, यहां हमारे एनपीई के साथ-साथ शून्य चेक-फ्री कोड भी है:

import java.util.Optional;
public class HomeServices {
    private static final int NOW = 0;
    private static Optional<HomeServices> service;

public static Optional<HomeServices> get() {
    service = Optional.of(service.orElse(new HomeServices()));
    return service;
}

public Optional<Service> getRefrigertorControl() {
    Service s = new  RefrigeratorService();
    //...
    return Optional.ofNullable(s);
}

public static void main(String[] args) {
    /* Get Home Services handle */
    Optional<HomeServices> homeServices = HomeServices.get();
    if(homeServices != null) {
        Optional<Service> refrigertorControl = homeServices.get().getRefrigertorControl();
        refrigertorControl.ifPresent(HomeServices::switchItOn);
    }
}

public static void switchItOn(Service s){
         //...
    }
}

पूरी पोस्ट एनपीई के साथ ही नल चेक-फ्री कोड है ... वास्तव में?




मैंने कोशिश की है NullObjectPatternलेकिन मेरे लिए हमेशा जाने का सबसे अच्छा तरीका नहीं है। कभी-कभी जब कोई "कोई कार्रवाई नहीं" अपरिपक्व नहीं होती है।

NullPointerExceptionएक रनटाइम अपवाद है जिसका अर्थ कि यह डेवलपर गलती है और पर्याप्त अनुभव के साथ यह आपको बताता है कि त्रुटि कहां है।

अब जवाब के लिए:

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

बेशक, अनुभव इस सुझाव को समझने और लागू करने का बेहतर तरीका है।

बाइट!




क्या मैं इसे अधिक आम तौर पर उत्तर दे सकता हूं!

हम आम तौर पर इस मुद्दे का सामना करते हैं जब विधियों को हमारे द्वारा अपेक्षित तरीके से पैरामीटर प्राप्त नहीं होते हैं (खराब विधि कॉल प्रोग्रामर की गलती है)। उदाहरण के लिए: आप ऑब्जेक्ट प्राप्त करने की अपेक्षा करते हैं, इसके बजाय आपको शून्य मिलती है। आप कम से कम एक चरित्र के साथ एक स्ट्रिंग प्राप्त करने की उम्मीद करते हैं, इसके बजाय आपको खाली स्ट्रिंग मिलती है ...

तो इसमें कोई अंतर नहीं है:

if(object == null){
   //you called my method badly!

}

या

if(str.length() == 0){
   //you called my method badly again!
}

वे दोनों यह सुनिश्चित करना चाहते हैं कि हम किसी भी अन्य कार्य करने से पहले, वैध पैरामीटर प्राप्त करें।

जैसा कि कुछ अन्य उत्तरों में बताया गया है, उपरोक्त समस्याओं से बचने के लिए आप अनुबंध पैटर्न द्वारा डिजाइन का पालन कर सकते हैं । कृपया http://en.wikipedia.org/wiki/Design_by_contract देखें ।

जावा में इस पैटर्न को लागू करने के लिए, आप javax.annotation.NotNull जैसे मूल जावा एनोटेशन का उपयोग कर सकते हैं या हाइबरनेट वैलिडेटर जैसे अधिक परिष्कृत पुस्तकालयों का उपयोग कर सकते हैं ।

बस एक नमूना:

getCustomerAccounts(@NotEmpty String customerId,@Size(min = 1) String accountType)

अब आप इनपुट पैरामीटर की जांच किए बिना अपनी विधि के मूल कार्य को सुरक्षित रूप से विकसित कर सकते हैं, वे आपके तरीकों को अप्रत्याशित पैरामीटर से सुरक्षित रखते हैं।

आप एक कदम आगे जा सकते हैं और सुनिश्चित कर सकते हैं कि आपके आवेदन में केवल वैध pojos बनाया जा सके। (हाइबरनेट सत्यापनकर्ता साइट से नमूना)

public class Car {

   @NotNull
   private String manufacturer;

   @NotNull
   @Size(min = 2, max = 14)
   private String licensePlate;

   @Min(2)
   private int seatCount;

   // ...
}



  1. शून्य को चर शुरू नहीं करें।
  2. यदि (1) संभव नहीं है, तो खाली संग्रह / सरणी के लिए सभी संग्रह और सरणी प्रारंभ करें।

इसे अपने कोड में करना और आप इससे बच सकते हैं! = शून्य जांच।

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

// Bad
ArrayList<String> lemmings;
String[] names;

void checkLemmings() {
    if (lemmings != null) for(lemming: lemmings) {
        // do something
    }
}



// Good
ArrayList<String> lemmings = new ArrayList<String>();
String[] names = {};

void checkLemmings() {
    for(lemming: lemmings) {
        // do something
    }
}

इसमें एक छोटा ओवरहेड है, लेकिन यह क्लीनर कोड और कम NullPointerExceptions के लिए इसके लायक है।




public static <T> T ifNull(T toCheck, T ifNull) {
    if (toCheck == null) {
           return ifNull;
    }
    return toCheck;
}



Related