ホームページ  >  記事  >  Java  >  Java の自動ボックス化およびボックス化解除ソース コード分析

Java の自動ボックス化およびボックス化解除ソース コード分析

WBOY
WBOY転載
2023-05-09 12:10:111254ブラウズ
    #梱包と開梱とは何ですか?

    int 基本型を Integer パッケージ型に変換するプロセスはボックス化と呼ばれ、その逆はアンボックス化と呼ばれます。

    最初にコードの一部を見てみましょう

    public static void main(String[] args) {
        Integer a = 127, b = 127;
        Integer c = 128, d= 128;
        System.out.println(a == b); // true
        System.out.println(c == d); // false
    }

    このコードに true と false が現れる理由を知らない人がいるかどうかはわかりません。ここからはJavaボクシングの操作を紹介します。質問を交えて分析していきます。

    Boxing (valueOf())

    public static Integer valueOf(int i) {
        // -128 - 127
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
    }

    先頭に判定があることがわかり、値の範囲が[-128,127]の場合はこのキャッシュから(整数配列) 、この範囲内にない場合は、新しいものを作成してください。

    なぜ [-128,127] のキャッシュが必要なのでしょうか?

    私たちのビジネスでは、ステータスや ID などのさまざまな整数型フィールドが存在する可能性があるため、私が話していることは理解できました。これらの値は通常、0、1、2、3 であり、キャッシュが存在しない場合、頻繁に新しいオブジェクトが必要になってから解放されるため、多くのメモリ領域が消費されます。そのため、キャッシュが表示され、領域の無駄を最適化するのに非常に役立ちます。

    なぜ [-128,127] なのでしょうか?

    これを見てみました。具体的な理由はここでは説明しませんが、主にコンピュータの基本的な知識に依存します。元のコード、逆コード、および補完コードが何であるかを理解した上で実行してください。なぜこの範囲内にあるのかを知るのは簡単です。

    この値は起動パラメータを通じて変更することもできます。

    -XX:AutoBoxCacheMax=(size)

    自動ボックス化によるパフォーマンスの問題

    これで、上記のコードの結果が異なる理由が理解できるはずです。たとえば、業務の for ループでこの操作と同様の統計データが発生した場合、自動ボックス化が行われた場合、どのような問題が発生するでしょうか?次のコードを見てみましょう。

    public static void main(String[] args) {
        long startTime = System.currentTimeMillis();
        Integer count = 0;
        // int count = 0;
        for (int i = 0; i < 5000000; i++) {
            count += i;
        }
        System.out.println("计算时长:" + (System.currentTimeMillis() - startTime) + " ms");
    }
    
    // 执行结果:
    // Integer 计算时长:51 ms
    // int 计算时长:6 ms

    その後、実行結果から、頻繁に新しいオブジェクトが自動的にボックス化され、メモリが割り当てられ、時間と空間のパフォーマンス損失が発生していることが明確にわかります。

    簡単なまとめ

    上記のソース コードの読み取りとテスト分析を通じて、通常、統計を計算したりメソッドにパラメーターを入力したりする場合は、このタイプを回避する必要があるという結論を導き出すことができます。 。コード全体の実行効率を向上させるため。

    アンボックス化 (intValue)

    アンボックス化には複雑なロジックはなく、値の基本型を直接返します。

    補足: 自動ボックス化とボックス化解除は常に行われますか? ######必ずしも。以下のサンプルコードを見てください。出力結果は出力ステートメントの後にコメント化されています。

    public static void main(String[] args) {
    // TODO 自动生成的方法存根
    Integer a = 1;
    Integer b = 2;
    Integer c = 3;
    Integer d = 3;
    Integer e = 321;
    Integer f = 321;
    Long g = 3L;
    System.out.println(c==d);//true
    //包装类的==在没有遇到算术运算的情况下不会自动拆箱
    System.out.println(e==f);//false
    System.out.println(c==(a+b));//true
    System.out.println(c.equals(a+b));//true
    System.out.println(g==(a+b));//true
    //equals方法不会处理数据转型关系
    System.out.println(g.equals(a+b));//false
    }

    自動ボックス化およびボックス化解除が発生する状況は次のとおりです。

    自動ボックス化: 基本タイプはパッケージング タイプに割り当てられます。例: Integer i1 = 1;

    自動開梱:

    パッケージ タイプは基本タイプに割り当てられます。例: int i2 = new Integer(1);
    1. int 型と Integer 型を比較します。 int型とInteger型の値が等しい場合、結果は常にtrueとなります。
    2. 整数型で算術演算が行われる
    3. しかし、なぜ上記の例では System.out.println(c==d); と System .out.println(e==f);出力結果が違う?
    主な原因は Integer.valueOf() メソッドです。 Integer のソース コードの一部を以下に示します。

      //
       private static class IntegerCache {
            static final int low = -128;
            static final int high;
            static final Integer cache[];
    
            static {
                // high value may be configured by property
                int h = 127;
                String integerCacheHighPropValue =
                    sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
                if (integerCacheHighPropValue != null) {
                    try {
                        int i = parseInt(integerCacheHighPropValue);
                        i = Math.max(i, 127);
                        // Maximum array size is Integer.MAX_VALUE
                        h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
                    } catch( NumberFormatException nfe) {
                        // If the property cannot be parsed into an int, ignore it.
                    }
                }
                high = h;
    
                cache = new Integer[(high - low) + 1];
                int j = low;
                for(int k = 0; k < cache.length; k++)
                    cache[k] = new Integer(j++);
    
                // range [-128, 127] must be interned (JLS7 5.1.7)
                assert IntegerCache.high >= 127;
            }
                private IntegerCache() {}
        }
        
      public static Integer valueOf(int i) {
            if (i >= IntegerCache.low && i <= IntegerCache.high)
                return IntegerCache.cache[i + (-IntegerCache.low)];
            return new Integer(i);
        }

    IntegerCache は Integer の静的内部クラスで、valueOf() はパッケージ化メソッドです。ソース コードからわかるように、cache はキャッシュ配列です。valueOf() メソッドの入力パラメータ i が [-128,127] の範囲にある場合、キャッシュ配列の整数値が返されます。それ以外の場合は、新しい値が返されます。整数が作成されます。

    System.out.println(c==d); と System.out.println(e==f); の出力結果が異なるのはこれが理由です。 c と d はキャッシュ間隔内にあるため、同じ参照を返します。一方、e と f はキャッシュ間隔内にないため、同じ参照ではない新しい整数を返します。

    以上がJava の自動ボックス化およびボックス化解除ソース コード分析の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

    声明:
    この記事はyisu.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。