जावा नल की जाँच करें कि। = का उपयोग क्यों करें। (असमान) के बजाय ()


125

जावा में मुझे बताया गया है कि अशक्त जांच करते समय किसी को असमान () के बजाय == का उपयोग करना चाहिए। इसके क्या कारण हैं?


12
सबसे आसान काम है, equals()देखने और देखने की कोशिश करना । जब आप कोशिश करते हैं तो यह तुरंत स्पष्ट हो जाएगा
गोरान जोविक

वैसे, कीवर्ड्स के साथ एक Google खोज "java null check" (बिना उद्धरण के) ने मुझे इस धागे में से एक शीर्ष हिट के रूप में दिया , जिसमें उत्तर के रूप में एक ही जानकारी है।
मिच श्वार्ट्ज

जवाबों:


179

वे दो पूरी तरह से अलग चीजें हैं। ==एक चर द्वारा निहित वस्तु संदर्भ, यदि कोई हो, की तुलना करता है। .equals()यह देखने के लिए जाँच करता है कि दो वस्तुओं को उनके अनुबंध के अनुसार समान होने का क्या मतलब है। यह दो अलग-अलग वस्तु उदाहरणों के लिए उनके अनुबंध के अनुसार "बराबर" होना पूरी तरह से संभव है। और फिर मामूली विस्तार है कि चूंकि equalsएक विधि है, यदि आप इसे एक nullसंदर्भ पर लागू करने का प्रयास करते हैं , तो आपको एक मिल जाएगा NullPointerException

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

class Foo {
    private int data;

    Foo(int d) {
        this.data = d;
    }

    @Override
    public boolean equals(Object other) {
        if (other == null || other.getClass() != this.getClass()) {
           return false;
        }
        return ((Foo)other).data == this.data;
    }

    /* In a real class, you'd override `hashCode` here as well */
}

Foo f1 = new Foo(5);
Foo f2 = new Foo(5);
System.out.println(f1 == f2);
// outputs false, they're distinct object instances

System.out.println(f1.equals(f2));
// outputs true, they're "equal" according to their definition

Foo f3 = null;
System.out.println(f3 == null);
// outputs true, `f3` doesn't have any object reference assigned to it

System.out.println(f3.equals(null));
// Throws a NullPointerException, you can't dereference `f3`, it doesn't refer to anything

System.out.println(f1.equals(f3));
// Outputs false, since `f1` is a valid instance but `f3` is null,
// so one of the first checks inside the `Foo#equals` method will
// disallow the equality because it sees that `other` == null

क्या आपका मतलब है public int data?
Jé Queue

@Xepoch: नहीं, मैं आम तौर पर सार्वजनिक क्षेत्र नहीं बनाता (हालाँकि यह इस तरह से वास्तव में मायने नहीं रखता है)। क्यों?
टीजे क्राउडर

@ टीटीजे क्राउडर "वे दो बिल्कुल अलग चीजें हैं .." सामान्य रूप से हाँ। हालांकि, दोनों की डिफ़ॉल्ट कार्यान्वयन समान है, अगर मेरी समझ सही है। स्रोत कोड को देखते हुए, .equals () मूल रूप से एक == चेक करता है। hg.openjdk.java.net/jdk7/jdk7/jdk/file/tip/src/share/classes/…
आयुष

1
@ आयुष - यही डिफ़ॉल्ट है Object, हाँ। हालांकि, JDK वर्गों की एक बड़ी संख्या द्वारा इसे ओवरराइड किया गया है। लेकिन कार्यान्वयन के बारे में बात नहीं है, यह शब्दार्थ के बारे में है। (साइड नोट: JDK7 बहुत पुराना है।)
TJ Crowder

ठीक है, यह समझ में आता है, बस स्पष्ट करना चाहता था।
आयुष

38

अगर तुम आह्वान .equals()करते हो nullतो तुम पाओगेNullPointerException

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

if(str!=null && str.equals("hi")){
 //str contains hi
}  

और देखें


34
आपका उदाहरण आम तौर पर बेहतर लिखा जाता है if ("hi".equals(str))
कॉलिनड डे

3
@ user368186: मुद्दा यह नहीं है कि बराबरी पद्धति में एक अशक्त जांच शामिल है। यदि आपका ऑब्जेक्ट संदर्भ रिक्त है, तो कॉल someObject.equals(null)एक बढ़ा देंगे NullPointerExceptionकभी प्रवेश करने विधि के बराबर होती है बिना।
डेव कोस्टा

2
@ColinD यहां सिर्फ प्रदर्शन कर रहा है
जिगर जोशी

2
यह हमेशा हर कीमत पर नल से बचने के लिए सलाह दी जाती है, इसलिए आपको अशक्त जांच की आवश्यकता नहीं है;)।
fwielstra

2
आप हमेशा इसका उपयोग कर सकते हैं Objects.equals(a, b)यह NullPointerException को नहीं बढ़ाएगा, लेकिन यह अभी भी "a" और "b" के "बराबर" तरीके पर निर्भर करता है
डोमिनिक Minc

29

स्वीकृत उत्तर के अलावा ( https://stackoverflow.com/a/4501084/6276704 )

जावा 1.7 के बाद से, यदि आप दो वस्तुओं की तुलना करना चाहते हैं, जो शून्य हो सकती हैं, तो मैं इस फ़ंक्शन की सलाह देता हूं:

Objects.equals(onePossibleNull, twoPossibleNull)

java.util.Objects

इस वर्ग में वस्तुओं के संचालन के लिए स्थैतिक उपयोगिता के तरीके शामिल हैं। इन उपयोगिताओं में किसी वस्तु के हैश कोड की गणना करने, किसी वस्तु के लिए स्ट्रिंग लौटाने और दो वस्तुओं की तुलना करने के लिए शून्य-सुरक्षित या अशक्त-सहिष्णु तरीके शामिल हैं।

चूंकि: 1.7


2
बस इसे दूसरों के लिए और अधिक दृश्यमान बनाने के लिए (chin90 के उत्तर या JavaDoc देखें ): Objects.equals(null, null)वापस आ जाएगा true- इसे ध्यान में रखें।
थॉमस

20

जावा में 0 या नल सरल प्रकार हैं और न कि वस्तुएं।

विधि समान () सरल प्रकारों के लिए नहीं बनाई गई है। सरल प्रकार == के साथ मिलान किया जा सकता है।


4
वास्तविक उत्तर के लिए अपवोट करें जो स्पष्ट "NullPointerException" के विपरीत सबसे उपयोगी है, "हर्प डर्बी उत्तर" को वापस कर दिया जाएगा।
Volk


3

यदि कोई ऑब्जेक्ट चर शून्य है, तो कोई उस पर एक समान () विधि नहीं कह सकता है, इस प्रकार नल का ऑब्जेक्ट संदर्भ चेक उचित है।


2

यदि आप एक अशक्त वस्तु संदर्भ पर बराबर कॉल करने का प्रयास करते हैं, तो आपको एक अशक्त सूचक अपवाद मिलेगा।


2

सूत्रों के अनुसार यह महत्वपूर्ण नहीं है कि डिफ़ॉल्ट विधि कार्यान्वयन के लिए क्या उपयोग किया जाए:

public boolean equals(Object object) {
    return this == object;
}

लेकिन आप equalsकस्टम क्लास के बारे में निश्चित नहीं हो सकते ।


यह मायने रखता है, क्योंकि equalsकेवल वापस आ falseसकता है NullPointerExceptionया एक (या कुछ अलग हो सकता है अगर ओवरराइड equalsविधि बकवास है)।
टॉम

2

यदि हम => .equals विधि का उपयोग करते हैं

if(obj.equals(null))  

// Which mean null.equals(null) when obj will be null.

जब आपका obj null होगा तो यह Null Point Exception को फेंक देगा।

इसलिए हमें == का उपयोग करना चाहिए

if(obj == null)

यह संदर्भों की तुलना करेगा।


2

Object.equals शून्य सुरक्षित है, हालाँकि इस बात से अवगत रहें कि यदि दो ऑब्जेक्ट्स अशक्त हैं, तो object.equals सही रूप से वापस आ जाएंगे, इसलिए यह सुनिश्चित कर लें कि जिन ऑब्जेक्ट्स की आप तुलना कर रहे हैं, वे ऑब्जेक्ट का उपयोग करने से पहले null (या शून्य मानों को होल्ड) न करें। तुलना।

String firstname = null;
String lastname = null;

if(Objects.equals(firstname, lastname)){
    System.out.println("equal!");
} else {
    System.out.println("not equal!");
}

उदाहरण के स्निपेट ऊपर बराबर लौटेंगे!


जैसा कि JavaDoc ने कहा है (यह हमेशा उन लोगों को पढ़ने के लिए बुद्धिमान है): Consequently, if both arguments are null, true is returned. ...:)
थॉमस

1

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


खैर, परिणाम केवल falseया NullPointerException(यदि equalsकुछ बुरा करने के लिए अतिरंजित नहीं है) हो सकता है।
टॉम

1

यहाँ एक उदाहरण है, str != nullलेकिन str.equals(null)जब उपयोग कर रहा हैorg.json

 JSONObject jsonObj = new JSONObject("{field :null}");
 Object field = jsonObj.get("field");
 System.out.println(field != null);        // => true
 System.out.println( field.equals(null)); //=> true
 System.out.println( field.getClass());  // => org.json.JSONObject$Null




संपादित करें: यहाँ org.json.JSONObject $ Null वर्ग है:

/**
 * JSONObject.NULL is equivalent to the value that JavaScript calls null,
 * whilst Java's null is equivalent to the value that JavaScript calls
 * undefined.
 */
private static final class Null {

    /**
     * A Null object is equal to the null value and to itself.
     *
     * @param object
     *            An object to test for nullness.
     * @return true if the object parameter is the JSONObject.NULL object or
     *         null.
     */
    @Override
    public boolean equals(Object object) {
        return object == null || object == this;
    }  
}

यहां मुद्दा यह है कि field.equals(null)रिटर्न सही है। यह सामान्य जावा व्यवहार को तोड़ता है और इसलिए भ्रामक है। यह केवल field.equals("null")मेरे दृष्टिकोण में, कम से कम काम करना चाहिए । मुझे नहीं पता कि पुस्तकालय डेवलपर्स ने क्यों सोचा, कि यह समर्थन करना अच्छा होगा।
टॉम

Btw, आपके पहले वाक्य में एक व्याकरण मुद्दा है और यह स्पष्ट नहीं है कि आप इसके साथ क्या मतलब है। क्या आपका मतलब है "एक उदाहरण है जहाँ है str != nullऔर str.equals(null)बदले trueका उपयोग करते समय org.json ।"?
टॉम

मुझे लगता है कि क्योंकि jsonObject"फ़ील्ड" कुंजी में यह है कि क्यों fieldअशक्त नहीं है, यह एक संदर्भ है जिसमें json.org.JSONObject$Null वस्तु शामिल है
दिनाँक

हाँ, पर मैं इलाज नहीं होता Nullकी तरह nullऔर प्रयोग करेंगे "null"बजाय। लेकिन मुझे लगता है कि उन्होंने स्ट्रिंग्स की आवश्यकता से बचने के लिए ऐसा किया है। लेकिन उस परिवाद के साथ, field.equals(null)अभी भी लगभग हमेशा एक मुद्दा है: पी।
टॉम

0

इसलिए मैं कभी भ्रमित नहीं होता और इस समाधान के साथ समस्याओं से बचता हूं:

if(str.trim().length() <=0 ) {
   // is null !
}

5
अगर str null है तो यह एक NPE
टाइपोप्रोप

इसके अतिरिक्त एक खाली स्ट्रिंग ( ""लंबाई 0) एक nullसंदर्भ (यानी कोई स्ट्रिंग) की तुलना में पूरी तरह से अलग है ।
थॉमस

0

मैंने कल रात इस मामले का सामना किया है।
मैं यह निर्धारित करता हूं कि बस:

अस्तित्व में नहीं है बराबर () विधि के लिए अशक्त
तो, आप नहीं कर सकते आह्वान एक गैर-मौजूद विधि अगर आपके पास नहीं है
- >>> यही कारण है कि हम प्रयोग के लिए कारण है == जाँच करने के लिए अशक्त


0

आप कोड तोड़ते हैं Demeter कानून। इसीलिए बेहतर है कि डिज़ाइन को ही रिफ्लेक्टर करें। वैकल्पिक हल के रूप में, आप वैकल्पिक का उपयोग कर सकते हैं

   obj = Optional.ofNullable(object1)
    .map(o -> o.getIdObject11())
    .map(o -> o.getIdObject111())
    .map(o -> o.getDescription())
    .orElse("")

उपरोक्त किसी वस्तु के पदानुक्रम की जाँच करना है, इसलिए बस उपयोग करें

Optional.ofNullable(object1) 

अगर आपके पास जांच के लिए केवल एक ही वस्तु है

उम्मीद है की यह मदद करेगा !!!!


-3

आप हमेशा कर सकते हैं

if (str == null || str.equals(null))

यह पहले ऑब्जेक्ट रेफरेंस की जाँच करेगा और फिर ऑब्जेक्ट को अपने आप में रेफरेंस नहीं करेगा।


if (str == null || str.equals (नल) || str.equals (""))
Lou

मैंने आपके उत्तर का उपयोग किया और एक खाली स्ट्रिंग के लिए एक चेक जोड़ा! अगर im गलत नहीं है, तो अशक्त और "" एक ही बात नहीं है।
लू मोर्डा

4
क्या अशक्त के लिए दूसरा चेक जोड़ना पूरी तरह से बेमानी है?
जस्टिन रोवे

2
@JustinRowe यह केवल बेमानी नहीं है, यह बहुत गलत भी है। कृपया, कभी कुछ ऐसा न करें x.equals(null)
टॉम 12

@Tom, JustinRowe कृपया ऊपर मेरा उत्तर क्यों इस निरर्थक है और न ही पूरा कचरा नहीं है stackoverflow.com/questions/4501061/...
दीना
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.