あなたは本当にロングまあでJavaを理解していますか?

実際の開発では、我々は非常に多くあるべき状況のロングタイプを使用しています。しかし、あなたは本当に完全にロングタイプのものを把握しますか?

テストコード

まず、テストコードを見てください。このコードは、テストすることができます。

    @Test
    public void testLong() {
        long primaryLong = 127L;
        Long long1 = Long.valueOf(primaryLong);
        Long long2 = 127L;

        Assert.assertTrue(long1 == long2); // 1

        long1 = new Long(127L);
        Assert.assertFalse(long1 == long2); // 2

        primaryLong = 128L;
        long1 = Long.valueOf(primaryLong);
        long2 = 128L;

        Assert.assertFalse(long1 == long2);  // 3

        long1 = new Long(128L);
        Assert.assertFalse(long1 == long2);  // 4
    }
复制代码

上記のテストコードでは、我々は変数long1ロングとLong2の2種類の平等を比較し、ここでは「==」演算子、2つの変数の参照が等しいテストに使用したアドレスを使用しています。

新しいロング()、Long.valueOf()と自動包装:シニアコード農家は、3つの方法がありますロングを作成している必要があります。コードは、その結果は、3つの方法で得られた実証します。

  • 解析コード注trueに1を返します。値127Lを使用する場合、関係なくLong.valueOfロング変数割り当てはロングタイプに長いオートボクシング作成または使用することは、このショーは、二つの変数が同じ場所を指します。
  • コード注の分析2はfalseを返します。自動包装だけの使用とロング(127L)ロング変数のうち、新たな創造の使用は、同じ場所にもはやポイントロング変数を作成したことをこの番組。
  • 偽の分析3,4コード注戻ります。それは新しいロング、Long.valueOf又は自動包装であるかどうか、このショーは、使用中の値は、別の場所に、各ポインティングをロング変数を作成128L。

これはどのように起こっていますか?結果は同じでない場合に特にLong.valueOfまたはこれらの2つの方法の自動包装のために、それは127Lと128Lに実際にありますか?

上記のコードは、このような結果である理由を完全に理解するために、我々はソースコードからスタートしなければなりませんでした。

分析

私たちは、オープンソースのコードをjava.lang.Longの。次のように前記キーコードがあります。

public final class Long extends Number implements Comparable<Long> {
    private final long value; // 1

    private static class LongCache { // 2
        private LongCache(){} // 2.1

        static final Long cache[] = new Long[-(-128) + 127 + 1]; // 2.2

        static { // 2.3
            for(int i = 0; i < cache.length; i++)
                cache[i] = new Long(i - 128);
        }
    }

    @Deprecated(since="9")
    public Long(long value) { // 3
        this.value = value;
    }

    @Deprecated(since="9")
    public Long(String s) throws NumberFormatException { // 4
        this.value = parseLong(s, 10);
    }

    public static Long valueOf(long l) { // 5
        final int offset = 128;
        if (l >= -128 && l <= 127) { // will cache
            return LongCache.cache[(int)l + offset];
        }
        return new Long(l);
    }
}
复制代码
  • 基本クラスからのロングNumberクラスの継承、抽象クラスは、クラス番号、代表者の数です。次の図に示す数から整数、ロング、バイト、ショート、floatとdoubleを継承。

    抽象メソッドXXXValueの唯一のいくつかの種類。図に示すように。

  • ロングノート1の分析は長い元のデータタイプを格納するために、内部実際に店舗や変数値を表します。

  • 注分析は2つの方法が値を割り当て、他の処理である、3,4-ロング2工法です。

  • 私たちは分析注2と5を見て:分析注2は、内部の静的クラスLongCacheは、名前から判断すると、クラスはキャッシュのロングタイプである必要があります:

    • 注分析は、そのクラスのインスタンスを防ぐために、2.1 LongCacheプライベートコンストラクタを示します。プライベートコンストラクタは、典型的には、ツールまたは単一インスタンスのクラスで使用され、例えば共通の単一モードの実施形態は、プライベートコンストラクタを必要とします。
    • 発現NOTEクラスの2.2分析ロングアレイキャッシュを有しており、静的最終的修飾を有します。配列のサイズ-(-128) + 127 + 1=256
      最後の配列は、あなたがすることはできませんそれらを再割り当て、初期化、それでも次のターゲットをキャッシュする配列の各要素の基準値を変更することができます。
    • 表現キャッシュノートの2.3分析が初期化。0から256個の添字は、-128と128の間の値に初期化されます。
  • 次に、パラメータLは、-128と127の間の値である解析を参照注5は、添字に対応する直接LongCache内部キャッシュ・アレイの値を返します。ここでオフセットそれによって最小のインデックス値を設定することは非常に巧妙なセット128は、オフセット= 0 -128(INT)L +です。これは、このような値の[-128、127]の範囲、新しいロングコールが戻るには属していません。

  • 同時に、の施工方法に注意を払う@Deprecated(since="9")開始からJDK9を示す注釈は、コンストラクタが推奨されていません。JDKのドキュメントは、より良い空間と時間のパフォーマンスを得ることができますLong.valueOfロングオブジェクトを構築するために、静的なファクトリメソッドを使用することをお勧めします。

標準文法によると、実際に呼び出して自動包装ではなく、コンストラクタよりも、Long.valueOfです。

上記分析、[-128、127]の値は、Long.valueOfパッキンを使用しているかどうか、または自動的に、最終的にそれに値LongCache.cacheを読み取る被写体であるため、「==」も同様です。他の例は、それぞれ異なる変数「==」比較の2はfalseです。

広げます

  • ショートクラス、クラスソースコードShortCacheのvalueOf方法およびロング同一の実装。ここでは行われません。
  • バイト・クラスのための、唯一127 -128の間の値を受信します。valueOfメソッドは、すべての値ShortCache.cacheを返すことができます。
  • floatとdoubleクラスの場合、無FloatCacheとDoubleCacheいわゆる、そのたびに新しいオブジェクトが構築されます。
  • 「==」の結果の違いを避けるために上記のコードの比較が表示されますに登場。推薦対象、使用または間の比較は、比較「==」取り外し可能な包装再利用の元の型に等しく、上記テストコードがlong1.longValue(使用可能)、または長いを+ long1、長いに変換します使用「==」の比較

注、+ long1は+のlong1がnullを返さないことを確認する必要があります。それ以外の場合は、NullPointerExceptionが報告されます。


私たちは理解してどのように参照するにはここで少しテスト?

Long long1 = new Long(100L);
Long long2 = 100L;
Long long3 = 100L;
Long long4 = 128L;
Long long5 = 128L;

System.out.println(long1 == long2);
System.out.println(+long1 == long2);

System.out.println(long2 == long3);
System.out.println(+long2 == long3);

System.out.println(long4 == long5);
System.out.println(+long4 == long5);
复制代码

あなたは上記のコードの出力をどう思いますか?

答え

false
true
true
true
false
true
复制代码

おすすめ

転載: juejin.im/post/5e6ada0fe51d45271849f498