[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つ目の方法で直接値を割り当てる場合、コードは次のとおりです.
作成済みのJavaファイルは、実行前にClassファイルにコンパイルされます.次に、コンパイルされたClassファイルを逆コンパイルし、次のコードを取得します.
逆コンパイルされたコードの内容を表示することで,Javaファイルのコンパイル後の内容が第1の方法の操作と一致していることが分かった.これは、実際にJavaの基本タイプとパッケージクラス間の変換が、JDK 5以降は手動で操作されるのではなく、Javaコンパイラによって支援され、Javaの仮想マシンとは何の関係もありません.
下層原理分析
これまでJava 5の自動梱包と解体の内容をほぼ把握してきました.実際の開発では,現在はJava 5以降のバージョンが基本的に使用されているため,自動梱包と解体の内容はそれほど重要ではない.次に例を示します.
上記の例では、変数Integerタイプのi 1,i 2,i 3,i 4はいずれも自動箱詰めであるが、最終的に比較した結果は1つがtrue、1つがfalseである.これは私たちを困惑させます.原因は何ですか.次に、自動梱包を復元します.上のコードは次のように書き換えることができます.
その後のコードを書き換えることで,元のIntegerタイプのvalueOf()メソッドが100と200で返される内容を受信するのは異なることが分かった.では、IntegerタイプのvalueOf()メソッドのソースコードを見てみましょう.それはいったいどうなっていますか.
ソースコードを見てみると、Integerクラスの内部には-128~127の間の256個のIntegerオブジェクトがキャッシュされており、valueOf()メソッドでこの範囲のintタイプの整数をIntegerオブジェクトに変換すると、キャッシュ内の内容が直接返され、そうでなければ再作成されたIntegerオブジェクトが返されます.したがって、上記の例では、整数100はIntegerクラスのキャッシュ中にあるので、そのままキャッシュ内容を返す.整数200はIntegerクラスのキャッシュに含まれていないので、Integerオブジェクトを再作成して返す必要があります.一方、2つのIntegerタイプのオブジェクトを比較すると、オブジェクトアドレスが同じかどうかを判断するので、1つの結果はtrueで、1つの結果はfalseです.
転載説明:本文の作者と原文の接続を明記してください.ありがとうございます.
Javaには、基本タイプ(int,double,float,long,boolean,char,byte,short)と基本タイプパッケージクラス(Integer,Double,Float,Long,Boolean,Char,Byte,Short)があり、基本タイプとパッケージクラスの変換を実現するには、基本的に2つの方法があります.
自動梱包/解体の原理
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です.
転載説明:本文の作者と原文の接続を明記してください.ありがとうございます.