Java nullチェックなぜ.equals()の代わりに==を使用するか


125

Javaでは、nullチェックを行う場合、.equals()の代わりに==を使用する必要があると言われています。これの理由は何ですか?


12
最も簡単なのは、nullチェックを試してみるequals()ことです。試してみるとすぐにわかります
Goran Jovic 2010

ちなみに、「java null check」というキーワード(引用符なし)を使ったグーグル検索では、このスレッドのトップヒットの1つとして、このスレッドと同じ情報が含まれています。
ミッチシュワルツ2010

回答:


179

それらは2つのまったく異なるものです。==変数に含まれているオブジェクト参照があれば、それを比較します。.equals()2つのオブジェクトが等しいかどうかの契約に従って、2つのオブジェクトが等しいかどうかを確認します。2つの異なるオブジェクトインスタンスが契約に従って「等しい」ことは完全に可能です。そして、マイナーな詳細があります。それ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ですか?
JEキュー

@Xepoch:いいえ、私は通常、パブリックフィールドを作成しません(ただし、この例ではどちらの方法でも実際には重要ではありません)。どうして?
TJクラウダー2010

@TJ Crowder「彼らは二つの完全に異なるものだ……」一般的にはそうだ。ただし、私の理解が正しければ、両方のデフォルトの実装は同じです。ソースコードを見ると、.equals()は基本的に==チェックを行います。hg.openjdk.java.net/jdk7/jdk7/jdk/file/tip/src/share/classes/...
アユシュ

1
@Ayush- Objectはい、それがのデフォルトです。ただし、多数のJDKクラスによってオーバーライドされます。しかし、重要なのは実装ではなく、セマンティクスです。(補足:JDK7は非常に古くなっています。)
TJ Crowder

そう、それは理にかなっている、ただ明確にしたかっただけだ。
アユッシュ

38

あなたが起動した場合.equals()nullあなたが取得しますNullPointerException

したがって、適用される場所でメソッドを呼び出す前にnullをチェックすることを常にお勧めします

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

こちらもご覧ください


34
あなたの例は一般的にとしてよりよく書かれていif ("hi".equals(str))ます。
ColinD 2010

3
@ user368186:ポイントは、equalsメソッドにnullチェックが含まれているかどうかではありません。オブジェクト参照がnullの場合、呼び出しsomeObject.equals(null)NullPointerExceptionequalsメソッドに入ることなくを発生させます。
デイブ・コスタ

2
@ColinD同意するここでデモを行う
Joshi

2
常にnullを回避することをお勧めします。そのため、nullチェックはまったく必要ありません;)。
fwielstra 2010

2
いつでも使用できます。 Objects.equals(a, b)これはNullPointerExceptionを発生させませんが、それでも「a」と「b」の「等しい」メソッドに依存します
Dominik Minc

29

受け入れられた回答に加えて(https://stackoverflow.com/a/4501084/6276704):

Java 1.7以降、nullの可能性がある2つのオブジェクトを比較する場合は、次の関数をお勧めします。

Objects.equals(onePossibleNull, twoPossibleNull)

java.util.Objects

このクラスは、オブジェクトを操作するための静的ユーティリティメソッドで構成されています。これらのユーティリティには、オブジェクトのハッシュコードを計算し、オブジェクトの文字列を返し、2つのオブジェクトを比較するためのnullセーフまたはnullトレラントメソッドが含まれています。

以来:1.7


2
他の人から見やすくするために(chin90の回答またはJavaDocを参照):Objects.equals(null, null)戻りますtrue-覚えておいてください。
トーマス

20

Javaでは、0またはnullは単純型であり、オブジェクトではありません。

メソッドequals()は単純型用に作成されていません。単純型は==と照合できます。


4
明白な「NullPointerExceptionが返されます」herp derp回答とは対照的に、最も役立つ実際の回答に賛成票を投じます。
ヴォルク


3

Object変数がnullの場合、equals()メソッドを呼び出すことができないため、nullのオブジェクト参照チェックが適切です。


2

nullオブジェクト参照でequalsを呼び出そうとすると、nullポインタ例外がスローされます。


2

ソースによると、デフォルトのメソッド実装に何を使用するかは問題ではありません:

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

しかしequals、カスタムクラスでは確信が持てません。


は、(またはオーバーライドされたメソッドがナンセンスである場合は何か別の)をequals返すfalseか、または引き起こすことができるので重要です。NullPointerExceptionequals
トム

2

=> .equalsメソッドを使用する場合

if(obj.equals(null))  

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

objがnullになると、Nullポイント例外がスローされます。

したがって、==を使用する必要があります

if(obj == null)

参照を比較します。


2

Object.equalsはnullセーフですが、2つのオブジェクトがnullの場合、object.equalsはtrueを返すため、object.equalsを比較。

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. ...:)
Thomas

1

equalはObjectクラスから派生した関数なので、この関数はクラスのアイテムを比較します。nullと一緒に使用すると、falseが返されます。これは、クラスのコンテンツがnullではないためです。さらに==はオブジェクトへの参照を比較します。


まあ、結果はfalseor のみですNullPointerExceptionequals何か悪いものにオーバーライドされない場合)。
トム

1

ここに例がありますstr != nullstr.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)true を返すことです。これは通常のJavaの動作を破壊するため、混乱を招きます。それはfield.equals("null")、少なくとも私の観点では、でのみ機能するはずです。ライブラリ開発者がなぜこれをサポートするのが良いだろうと思ったのか、私にはわかりません。
トム

ところで、最初の文には文法の問題があり、それが何を意味するのかは不明です。あなたは「ここの例であることを意味しますstr != nullstr.equals(null)リターンtrue使っorg.jsonを。」?
トム

これはnullでないjsonObject理由である「フィールド」キーが含まれているためだと思いfieldます。json.org.JSONObject$Null オブジェクトを含む参照があります
dina

はい、しかし私はそのNullように扱わず、代わりにnull使用し"null"ます。しかし、私は彼らが文字列を必要としないようにするためにそれをしたと思います。しかし、そのlibを使用しfield.equals(null)ても、ほとんど常に問題です:P。
トム

0

だから私は決して混乱することはなく、この解決策の問題を回避します:

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

5
strがnullの場合、これはNPEになります
typoerrpr

さらに、空の文字列(""長さが0)は、null参照(文字列なし)とはまったく異なります。
トーマス

0

私は昨夜この事件に遭遇しました。
私はそれを単にそれと判断します:

存在しないのequals()メソッドのためのヌルを
あなたはできないので、たinvokeあなたが持っていない場合inexistent方法
>>>私たちが使用する理由の理由であること- ==をチェックするためにはnullを


0

あなたはコードがデメテルの法則を破ります。そのため、デザイン自体をリファクタリングする方が良いでしょう。回避策として、オプションを使用できます

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

上記はオブジェクトの階層をチェックすることなので、単純に使用します

Optional.ofNullable(object1) 

チェックするオブジェクトが1つしかない場合

お役に立てれば !!!!


-3

いつでもできる

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

これは、最初にオブジェクト参照をチェックしてから、参照がnullでない場合はオブジェクト自体をチェックします。


if(str == null || str.equals(null)|| str.equals( ""))
Lou Morda

私はあなたの答えを使って、空の文字列のチェックを追加しました!もし私が間違っていなければ、nullと ""は同じものではありません。
ルーモーダ

4
nullの2番目のチェックを追加することは完全に冗長ではありませんか?
ジャスティンロウ2014

2
@JustinRoweこれは冗長であるだけでなく、非常に間違っています。のようなことは絶対に行わないでくださいx.equals(null)
トム

@Tom、JustinRoweこれは冗長でも、完全なガベージない理由上記の私の答えを参照してください stackoverflow.com/questions/4501061/...
ディナ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.