技術共有

Java 128 トラップ

2024-07-12

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina

128トラップとは何ですか

まずはコードを見てみましょう

		int a0=127;
        int a1=127;
        Integer a2=127;
        Integer a3=127;
        System.out.println(a0==a1);  // 1、运行结果是true
        System.out.println(a0==a2);  // 2、运行结果是true
        System.out.println(a2==a3);  // 3、运行结果是true
        System.out.println(a2.equals(a0)); // 注意这里必须是包装类的a2才能使用equals,a0不能使用
                                           // 4、运行结果是true
        System.out.println(a2.equals(a3)); // 5、运行结果是true
        System.out.println("-----------------------------");

        int b0=200;
        int b1=200;
        Integer b2=200;
        Integer b3=200;
        System.out.println(b0==b1);	// 6、运行结果是true
        System.out.println(b0==b2);	// 7、运行结果是true
        System.out.println(b2==b3);// 8、运行结果是false
        System.out.println(b2.equals(b0)); // 9、运行结果是true
        System.out.println(b2.equals(b3)); // 10、运行结果是true
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 実行結果は期待どおりですか?
    実は8回目の走行結果はいわゆる128トラップです。

  • Java 128 トラップとは、基本型データのカプセル化クラスが保存する値が 128 以上の場合、各クラスのアドレスが等しくないことを指します。128 である必要はありません。

    簡単に言うと、127 以下で -128 以上の場合は、同じアドレスに存在する値が自動的にボックス化されます。127 より大きい場合は、その値がボックス化されます。自動的にボックス化されるものは同じものではありません。つまり、範囲が [-128,127] でない限り、== を使用すると false が返されます。 「equals」を使用した場合、結果は true になります。値は現在の範囲内にありませんが、Integer が使用されている場合は自動的にボックス化されず、128 トラップの問題は発生しないため、7 回目の実行は true になります。

なぜ128トラップが現れるのでしょうか?

ソースコードを表示する
	/**解释精简一部分后
     * This method will always cache values in the range -128 to 127
     */
	public static Integer valueOf(int i) {
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

例証します:
1. IntegerCache.low の値は -128、IntegerCache.high の値は 127 です。
2. Integer の valueOf メソッドには、-128 ~ 127 の閉間隔のキャッシュに相当するキャッシュ配列が格納されます。
3. 取得した値が [-128, 127] の間の場合、返される値は IntegerCache.cache 配列で定義された値であり、新しいオブジェクトを作成する必要はありません。
4. 値が範囲内にない場合、新しいオブジェクトを作成する必要があります。新しいオブジェクト == は、判定されたオブジェクトの値 (偽) です。

128の罠に直面する際の注意点

  • オブジェクトが new によって作成された場合 (以下に示すように)、128 トラップは存在しません。 (自動開梱・梱包作業です。後ほど紹介を書きます)
    その理由は、new によって生成されるオブジェクトのメモリ アドレスが異なり、比較されるオブジェクトが同じではないためです。
	Integer k1 = new Integer(100);
    Integer k2 = new Integer(100);
    System.out.println(k1==k2);  // 运行结果false
    System.out.println(k1.equals(k2)); // 运行结果true
  • 1
  • 2
  • 3
  • 4
  • 値を比較する場合は、equals メソッドを使用できます。


参考ドキュメント:
https://blog.csdn.net/niu_8865/article/details/110791911
https://blog.csdn.net/DianLanHong/article/details/119617352
https://blog.csdn.net/ヤンヨン_/article/details/135611919