[Java 5新機能]自動梱包/解体

4756 ワード

自動梱包/解体の概要
Javaには、基本タイプ(int,double,float,long,boolean,char,byte,short)と基本タイプパッケージクラス(Integer,Double,Float,Long,Boolean,Char,Byte,Short)があり、基本タイプとパッケージクラスの変換を実現するには、基本的に2つの方法があります.
  • JDK 5以前の方法、例えばInteger i=Integer.valueof(5);(ここで5は基本タイプint、Integerパッケージクラスはvalueof()メソッドでIntegerタイプに変換)またはint i=i.intValue()(ここで基本タイプはintValue()メソッドを用いてIntegerタイプを基本タイプintに変換する).
  • JDK 5の後の方法、例えば1 Integer i=5;または②int i=new Integer(100);ここでは基本タイプと包装類との間で直接操作可能であり、①の操作は自動梱包であり、②の操作は自動解体である.

  • 自動梱包/解体の原理
    2つ目の方法で直接値を割り当てる場合、コードは次のとおりです.
    public class Demo {
    
        @Test
    
        public void demo() {
    
            Integer integer = 5;
    
    
    
            int i = new Integer(100);
    
        }
    
    }
    
    

    作成済みのJavaファイルは、実行前にClassファイルにコンパイルされます.次に、コンパイルされたClassファイルを逆コンパイルし、次のコードを取得します.
    public class Demo {
    
        @Test
    
        public void demo() {
    
            Integer integer = Integer.valueOf(5);
    
    
    
            int i = new Integer(100).intValue();
    
        }
    
    }
    
    

    逆コンパイルされたコードの内容を表示することで,Javaファイルのコンパイル後の内容が第1の方法の操作と一致していることが分かった.これは、実際にJavaの基本タイプとパッケージクラス間の変換が、JDK 5以降は手動で操作されるのではなく、Javaコンパイラによって支援され、Javaの仮想マシンとは何の関係もありません.
    下層原理分析
    これまでJava 5の自動梱包と解体の内容をほぼ把握してきました.実際の開発では,現在はJava 5以降のバージョンが基本的に使用されているため,自動梱包と解体の内容はそれほど重要ではない.次に例を示します.
    public class Demo {
    
        @Test
    
        public void demo2() {
    
            Integer i1 = 100;
    
            Integer i2 = 100;
    
            boolean b1 = i1 == i2;
    
            System.out.println(b1);     //output true
    
    
    
            Integer i3 = 200;
    
            Integer i4 = 200;
    
            boolean b2 = i3 == i4;
    
            System.out.println(b2);     //output false
    
        }
    
    }
    
    

    上記の例では、変数Integerタイプのi 1,i 2,i 3,i 4はいずれも自動箱詰めであるが、最終的に比較した結果は1つがtrue、1つがfalseである.これは私たちを困惑させます.原因は何ですか.次に、自動梱包を復元します.上のコードは次のように書き換えることができます.
    public class Demo {
    
        @Test
    
        public void demo3() {
    
            Integer i1 = Integer.valueOf(100);
    
            Integer i2 = Integer.valueOf(100);
    
            boolean b1 = i1 == i2;
    
            System.out.println(b1);     //output true
    
            Integer i3 = Integer.valueOf(200);
    
            Integer i4 = Integer.valueOf(200);
    
            boolean b2 = i3 == i4;
    
            System.out.println(b2);     //output false
    
        }
    
    }
    
    

    その後のコードを書き換えることで,元のIntegerタイプのvalueOf()メソッドが100と200で返される内容を受信するのは異なることが分かった.では、IntegerタイプのvalueOf()メソッドのソースコードを見てみましょう.それはいったいどうなっていますか.
    public static Integer valueOf(int i) {
    
        if (i >= IntegerCache.low && i <= IntegerCache.high)
    
            return IntegerCache.cache[i + (-IntegerCache.low)];
    
        return new Integer(i);
    
    }
    
    

    ソースコードを見てみると、Integerクラスの内部には-128~127の間の256個のIntegerオブジェクトがキャッシュされており、valueOf()メソッドでこの範囲のintタイプの整数をIntegerオブジェクトに変換すると、キャッシュ内の内容が直接返され、そうでなければ再作成されたIntegerオブジェクトが返されます.したがって、上記の例では、整数100はIntegerクラスのキャッシュ中にあるので、そのままキャッシュ内容を返す.整数200はIntegerクラスのキャッシュに含まれていないので、Integerオブジェクトを再作成して返す必要があります.一方、2つのIntegerタイプのオブジェクトを比較すると、オブジェクトアドレスが同じかどうかを判断するので、1つの結果はtrueで、1つの結果はfalseです.
    転載説明:本文の作者と原文の接続を明記してください.ありがとうございます.