Objects.equals メソッドの落とし穴

はじめに: Objects.equals() メソッドは java.util のツール クラスで、これを使用すると、2 つのオブジェクトが等しいかどうかを比較し、面倒な null ポインタの判断を回避できます。

この記事では、コード例、ソース コードのブレークポイント デバッグによる分析、および Objects.equals() メソッドの使用時に見落とされやすいいくつかの問題によって拡張されています。

1. Objects.equals() 公式ソースコード

这里我们先看Objects.equals()的官方源码

    /**
     * Returns {@code true} if the arguments are equal to each other
     * and {@code false} otherwise.
     * Consequently, if both arguments are {@code null}, {@code true}
     * is returned and if exactly one argument is {@code null}, {@code
     * false} is returned.  Otherwise, equality is determined by using
     * the {@link Object#equals equals} method of the first
     * argument.
     *
     * @param a an object
     * @param b an object to be compared with {@code a} for equality
     * @return {@code true} if the arguments are equal to each other
     * and {@code false} otherwise
     * @see Object#equals(Object)
     */
    public static boolean equals(Object a, Object b) {
    
    
        return (a == b) || (a != null && a.equals(b));
    }

2. 以下のコードの実行結果を分析します。

    public static void main(String[] args) {
    
    
        Integer integer1 = Integer.valueOf(1);
        Integer integer200 = Integer.valueOf(200);
        Integer integer100 = Integer.valueOf(100);
        Long long200 = 200L;
        Byte Byte100 = (byte) 100;
        byte byte100 = (byte) 100;
        System.out.println("--------------------Integer-----------------------");
        System.out.println(Objects.equals(integer1, 1));         // true
        System.out.println(Objects.equals(integer200, 200));     // true
        System.out.println(Objects.equals(integer100, byte100));    // false
        System.out.println(Objects.equals(integer100, Byte100));    // false
        System.out.println("--------------------Long--------------------------");
        System.out.println(Objects.equals(long200, 200L));      // true
        System.out.println(Objects.equals(long200, 200));       // false
        System.out.println(Objects.equals(long200, integer200));    //false
        System.out.println("--------------------Byte--------------------------");
        System.out.println(Objects.equals(Byte100, 100));       // false
        System.out.println(Objects.equals(Byte100, (byte) 100));    // true
        System.out.println(Objects.equals(Byte100, byte100));       // true
        System.out.println("--------------------byte--------------------------");
        System.out.println(Objects.equals(byte100, 100));       // false
        System.out.println(Objects.equals(byte100, (byte) 100));   // true
        System.out.println(Objects.equals(100,byte100));        // false
    }

3. 主要な質問への回答

3.1 System.out.println(Objects.equals(integer100, byte100));

これら 2 つは両方とも です赋值100が、比較に Objects.equals() を使用すると、戻り値が false であることがわかります。これはなぜですか? 次に、図に示すように、ソース コードのデバッグを中断します。
ステップ 1、ブレークポイントを設定します
ここに画像の説明を挿入
。 ステップ 2、ブレークポイントで Objects.equals() メソッドにジャンプします。
byte100 基本データ型変数が削除されていることがわかります。自动装箱为Byte包装类, 次のステップは Integer の等しいメソッドです.
ここに画像の説明を挿入
3 番目のステップはメソッドに侵入することですInteger.equals(). Byte は Integer のインスタンスではないため, Integer.equals() メソッドは値を比較する代わりに直接 false を返すことがわかります。
ここに画像の説明を挿入

3.2 System.out.println(Objects.equals(long200, 200));

1 つは 200L、もう 1 つは 200 であり、これは慣性思考では間違いなく正しいと考えられますが、比較のために Objects.equals() を使用すると、これはなぜでしょうか返回的是false? 次に、図に示すように、ソース コードでデバッグを中断します。
ステップ 1、ブレークポイントを設定します。 ステップ 2、このことから、次のステップ3
ここに画像の説明を挿入
で基本データ型 (int) 200 が設定されていることがわかります。図に示すように、Long.equals() メソッド内でブレークポイントが直接ジャンプします。2 つはまったく同じオブジェクト型ではないため、直接 false を返します。原理は上記 3.1 と同じです。自动装箱为Integer
ここに画像の説明を挿入


ここに画像の説明を挿入

概要: 上記の問題の本質的な理由は、Object.equals() メソッドを使用すると、基本データ型が自動的にボックス化され、対応するラッパー クラスの等価比較が実行されることです。そして私たちはそれを無視し类型的比较、値の比較だけに注意を払いました。

ここまで言いましたが、実際には、これは Objects.equals() メソッドの落とし穴ではありません。私たちがこれを当然のこととして受け入れ、それがコンピュータ コードの実行と矛盾していることを理解しているだけです。このことから、次のこともわかります。理由。他社が作成したホイールを使用する場合は、コードを迅速かつ効率的に作成する際に、対応する機能の境界、使用シナリオ、および失敗のシナリオを明確にする必要があります。そうすることでのみ、バグの少ない正しいコードを作成することができます。

おすすめ

転載: blog.csdn.net/lzq2357639195/article/details/131166898