Java null, neden .equals () yerine == kullanıldığını kontrol edin


125

Java'da null kontrol yaparken .equals () yerine == kullanılması gerektiği söylendi. Bunun nedenleri nelerdir?


12
En kolay şey, ile boş kontrolü denemek equals()ve görmektir. Denediğinizde anında belli olacak
Goran Jovic

Bu arada, "java null check" (tırnak işaretleri olmadan) anahtar kelimelerini içeren bir google araması, buradaki cevaplarla aynı bilgilere sahip olan bu konudaki en iyi isabetlerden biri olarak bana verdi .
Mitch Schwartz

Yanıtlar:


179

Tamamen farklı iki şey. ==eğer varsa, bir değişkenin içerdiği nesne referansını karşılaştırır. eşitliğin ne anlama geldiği konusunda .equals()iki nesnenin sözleşmelerine göre eşit olup olmadığını kontrol eder . İki farklı nesne örneğinin sözleşmelerine göre "eşit" olması tamamen mümkündür. Ve sonra equalsbir yöntem olduğu için küçük bir ayrıntı var , eğer onu bir nullreferansta çağırmaya çalışırsanız , bir NullPointerException.

Örneğin:

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

demek public int dataistiyorsun
Jé Queue

@Xepoch: Hayır, genellikle genel alanlar oluşturmuyorum (bu örnek için her iki şekilde de önemli olmasa da). Neden?
TJ Crowder

@TJ Crowder "Bunlar tamamen farklı iki şey .." genel olarak evet. Ancak, anlayışım doğruysa, her ikisinin de varsayılan uygulaması aynıdır. Kaynak koduna bakıldığında, .equals () temelde bir == kontrolü yapar. hg.openjdk.java.net/jdk7/jdk7/jdk/file/tip/src/share/classes/…
Ayush

1
@Ayush - Bu varsayılan Object, evet. Yine de, çok sayıda JDK sınıfı tarafından geçersiz kılınır. Ama konu uygulama değil, anlambilimle ilgili. (Yan not: JDK7 çok güncel değil.)
TJ Crowder,

Doğru, bu mantıklı, sadece açıklığa kavuşturmak istedim.
Ayush

38

Eğer çağırmak varsa .equals()üzerine nullalacakNullPointerException

Bu nedenle, geçerli olduğu her durumda yöntemi çağırmadan önce geçersizliği kontrol etmeniz her zaman tavsiye edilir.

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

Ayrıca Bakın


34
Örneğiniz genellikle daha iyi yazılır if ("hi".equals(str)).
ColinD

3
@ user368186: önemli olan, eşittir yönteminin bir boş denetim içerip içermediği değildir. Nesne başvurunuz null ise, çağrı eşittir yöntemine hiç girmeden someObject.equals(null)a yükseltir NullPointerException.
Dave Costa

2
@ColinD Sadece burada gösteri yapıyoruz
Jigar Joshi

2
Her ne pahasına olursa olsun boş değerlerden kaçınmanız her zaman tavsiye edilir, böylece boş kontrollere hiç ihtiyacınız olmaz;).
fwielstra

2
Her zaman kullanabilirsiniz Objects.equals(a, b)NullPointerException'ı yükseltmez, ancak yine de "a" ve "b" nin "eşit" yöntemine bağlıdır
Dominik Minc

29

Kabul edilen cevaba ek olarak ( https://stackoverflow.com/a/4501084/6276704 ):

Java 1.7'den beri, boş olabilecek iki Nesneyi karşılaştırmak istiyorsanız, bu işlevi tavsiye ederim:

Objects.equals(onePossibleNull, twoPossibleNull)

java.util.Objects

Bu sınıf, nesneler üzerinde çalışmak için statik fayda yöntemlerinden oluşur. Bu yardımcı programlar, bir nesnenin karma kodunu hesaplamak, bir nesne için bir dize döndürmek ve iki nesneyi karşılaştırmak için boş güvenlikli veya boş toleranslı yöntemleri içerir.

Beri: 1.7


2
Sadece (chin90 cevabı ya da bkz diğerleri için daha görünür hale getirmek için Javadoc ): Objects.equals(null, null)dönecektir true- tutmak akılda.
Thomas

20

Java'da 0 veya null basit türlerdir ve nesneler değildir.

Eşittir () yöntemi basit türler için oluşturulmamıştır. Basit türler == ile eşleştirilebilir.


4
bariz "NullPointerException döndürülecek" herp derp cevabının tersine en yararlı olan gerçek yanıtı yükseltin.
volk

4
foo.equals(null)

Foo null olursa ne olur?

NullPointerException alırsınız.


3

Bir Object değişkeni null ise, bunun üzerine bir equals () yöntemi çağrılamaz, dolayısıyla boş olan bir nesne referans kontrolü uygundur.


2

Boş bir nesne başvurusunda eşittir çağırmayı denerseniz, atılan bir boş işaretçi istisnası alırsınız.


2

Kaynaklara göre, varsayılan yöntem uygulaması için ne kullanılacağı önemli değil:

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

Ancak equalsözel sınıfta emin olamazsınız .


Bu önemlidir, çünkü equalsyalnızca a'ya (veya geçersiz kılma yöntemi anlamsızsa farklı falsebir NullPointerExceptionşeye) geri dönebilir veya neden olabilir equals.
Tom

2

=> .Equals yöntemini kullanırsak

if(obj.equals(null))  

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

Nesneniz boş olduğunda Null Point Exception atacaktır.

bu yüzden == kullanmalıyız

if(obj == null)

referansları karşılaştıracaktır.


2

Object.equals boş güvenlidir, ancak iki nesne boşsa, object.equals true döndürür, bu nedenle object.equals'ı kullanmadan önce karşılaştırdığınız nesnelerin boş olmadığını (veya boş değerleri tuttuğunu) kontrol ettiğinizden emin olun. karşılaştırması.

String firstname = null;
String lastname = null;

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

Yukarıdaki örnek snippet eşit olarak dönecektir!


JavaDoc tarafından belirtildiği gibi (bunları okumak her zaman akıllıca olacaktır): Consequently, if both arguments are null, true is returned. ...:)
Thomas

1

Eşit, Object sınıfından türetilmiş bir işlev olduğundan, bu işlev sınıfın öğelerini karşılaştırır. Eğer onu null ile kullanırsanız, yanlış bir sebep döndürür, çünkü sınıf içeriği boş değildir. Ek olarak == bir nesneye yapılan referansı karşılaştırır.


Eh, sonuç sadece falseveya olabilir NullPointerException(eğer equalskötü bir şeye geçersiz kılınmamışsa).
Tom

1

burada bir örnek str != nullama str.equals(null)kullanırkenorg.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




DÜZENLEME: işte org.json.JSONObject $ Null sınıfı:

/**
 * 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;
    }  
}

Buradaki sorun, field.equals(null)gerçeğe dönmesidir. Bu olağan Java davranışını bozar ve bu nedenle kafa karıştırıcıdır. field.equals("null")En azından benim bakış açıma göre işe yaramalı. Kütüphane geliştiricilerinin neden bunu desteklemek için iyi olacağını düşündüklerini bilmiyorum.
Tom

Btw, ilk cümlenin bir gramer sorunu var ve onunla ne demek istediğin belli değil. Yani "İşte org.json kullanılırken nereye str != nullve str.equals(null)döndüğüne bir örnek " mi? true
Tom

Sanırım bunun nedeni jsonObject"alan" anahtarını içerdiği için bu yüzden fieldboş değil, json.org.JSONObject$Null nesneyi içeren bir referansı var
dina

Evet, ama tedavi olmaz Nullgibi nullve kullanmak "null"yerine. Ama sanırım bunu Strings gerektirmemek için yaptılar. Ama bu bile lib ile, field.equals(null)hala neredeyse her zaman bir sorun: P.
Tom

0

Bu yüzden asla kafam karışmaz ve bu çözümle ilgili sorunlardan kaçınmam:

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

5
Str
boşsa

Ek olarak, boş bir dize ( ""uzunluğu 0 olan) bir nullreferanstan tamamen farklı bir şeydir (yani dize yok ).
Thomas

0

Dün gece bu davayla karşılaştım.
Bunu basitçe belirledim:

Null için equals () yöntemi yok Bu nedenle, eğer sahip değilseniz, varolmayan bir yöntemi çağıramazsınız - >>> Kontrol etmek için == kullanmamızın nedeni budur

null adlı


0

Kodun Demeter kanununu çiğniyorsun. Bu yüzden tasarımın kendisini yeniden düzenlemek daha iyidir. Geçici bir çözüm olarak, İsteğe bağlı

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

yukarıdaki bir nesnenin hiyerarşisini kontrol etmektir, bu nedenle

Optional.ofNullable(object1) 

kontrol edilecek tek bir nesneniz varsa

Bu yardımcı olur umarım !!!!


-3

Her zaman yapabilirsin

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

Bu, önce nesne referansını kontrol edecek ve ardından referansın boş olmadığını sağlayarak nesnenin kendisini kontrol edecektir.


eğer (str == null || str.equals (null) || str.equals (""))
Lou

Cevabınızı kullandım ve boş bir dizge için bir kontrol ekledim! yanılmıyorsam, boş ve "" aynı şey değildir.
Lou Morda

4
Boş değer için 2. bir kontrol eklemek tamamen gereksiz değil mi?
Justin Rowe

2
@JustinRowe Sadece gereksiz değil, aynı zamanda çok da yanlış. Lütfen, asla böyle bir şey yapma x.equals(null).
Tom

Bu gereksiz ne de tam çöp değildir neden @Tom, JustinRowe yukarıda benim cevap bakınız stackoverflow.com/questions/4501061/...
dina
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.