この記事では、 autoboxing/unboxing と呼ばれる Java の機能について説明します。オートボックス化とアンボックス化は、プリミティブ型をオブジェクト型に、またはその逆に変換する機能です。 プロセス全体は Java ランタイム環境 (JRE) によって自動的に実行されます。ただし、この関数を実装する場合は注意が必要です。プログラムのパフォーマンスに影響を与える可能性があります。
表 1:比較演算子を使用したプリミティブ型と同等のラッパー クラス オートボクシングとアンボックス化は、比較演算子とともに使用できます。次のコード スニペットは、これがどのように起こるかを示しています。 リスト 3:比較演算子を使用したオートボックス化とアンボックス化を示すサンプル コード
導入
JDK 1.5 より前のバージョンでは、int
、char
、float
、などのプリミティブ データ型をdouble
そのラッパー クラス Integer、Character、Float、Double に変換するのは簡単ではありませんでした。JDK 5 以降では、プリミティブ型を同等のオブジェクトに変換するこの機能が自動的に実装されます。このプロパティはオートボクシングとして知られています。逆のプロセスは、それぞれUnboxingです。オブジェクトを対応するプリミティブ型に変換するプロセス。オートボックス化およびボックス化解除のサンプル コードを以下に示します 。
Integer integer = 9;
開梱する
int in = 0;
in = new Integer(9);
自動梱包と開梱はどのような場合に使用されますか? オートボクシングは、次の条件下で Java コンパイラによって使用されます。
- プリミティブ型の値がメソッド パラメーターとしてメソッドに渡される場合、対応するラッパー クラスのオブジェクトが期待されます。
- プリミティブ型の値が、対応するラッパー クラスの変数に割り当てられる場合。
public int sumEvenNumbers(List<Integer> intList ) {
int sum = 0;
for (Integer i: intList )
if ( i % 2 == 0 )
sum += i;
return sum;
}
jdk 1.5 より前では、剰余演算子 % と単項プラス += をラッパー クラスに適用できなかったため、上記のコードはコンパイル エラーを引き起こしていました。ただし、jdk 1.5 以降では、このコードはエラーなしでコンパイルされ、Integer が に変換されますint
。ボックス化解除は、次の条件下で Java コンパイラーによって使用されます。
- 対応するプリミティブ型を期待するメソッドにオブジェクトがパラメータとして渡される場合。
- オブジェクトが対応するプリミティブ型の変数に割り当てられるとき。
import java.util.ArrayList;
import java.util.List;
public class UnboxingCheck {
public static void main(String[] args) {
Integer in = new Integer(-8);
// 1. Распаковка через вызов метода
int absVal = absoluteValue(in);
System.out.println("absolute value of " + in + " = " + absVal);
List<Double> doubleList = new ArrayList<Double>();
// Автоупаковка через вызов метода
doubleList.add(3.1416);
// 2. Распаковка через присвоение
double phi = doubleList.get(0);
System.out.println("phi = " + phi);
}
public static int absoluteValue(int i) {
return (i < 0) ? -i : i;
}
}
オートボックス化とアンボックス化により、開発者は読みやすく理解しやすいコードを作成できます。次の表は、プリミティブ データ型とそれに対応するラッパー オブジェクトを示しています。
プリミティブ型 | シェルクラス |
---|---|
ブール値 | ブール値 |
バイト | バイト |
チャー | キャラクター |
浮く | 浮く |
整数 | 整数 |
長さ | 長さ |
短い | 短い |
public class BoxedComparator {
public static void main(String[] args) {
Integer in = new Integer(25);
if (in < 35)
System.out.println("Value of int = " + in);
}
}
メソッドのオーバーロード時の自動パッキングとアンパック メソッドのオーバーロード時には、次のルールに基づいて自動パッキングとアンパックが実行されます。
- 拡張とパッケージングのどちらかを選択できる状況では、拡張はパッケージングを「無効」にし、拡張することが望ましいです。
public class WideBoxed {
public class WideBoxed {
static void methodWide(int i) {
System.out.println("int");
}
static void methodWide( Integer i ) {
System.out.println("Integer");
}
public static void main(String[] args) {
short shVal = 25;
methodWide(shVal);
}
}
}
プログラム出力 - タイプint
- 拡張は引数の可変数に勝ります 拡張か引数の可変数のどちらかを選択する必要がある状況では、拡張の方が望ましいです。
public class WideVarArgs {
static void methodWideVar(int i1, int i2) {
System.out.println("int int");
}
static void methodWideVar(Integer... i) {
System.out.println("Integers");
}
public static void main( String[] args) {
short shVal1 = 25;
short shVal2 = 35;
methodWideVar( shVal1, shVal2);
}
}
- パッキングは引数の可変数に勝ります パッキングと引数の可変数のどちらかを選択する必要がある状況では、パッキングが推奨されます。
public class BoxVarargs {
static void methodBoxVar(Integer in) {
System.out.println("Integer");
}
static void methodBoxVar(Integer... i) {
System.out.println("Integers");
}
public static void main(String[] args) {
int intVal1 = 25;
methodBoxVar(intVal1);
}
}
自動パッキングを使用するときは、次のことに留意する必要があります。 ご存知のとおり、すべての優れた機能には欠点があります。この点では、自動梱包も例外ではありません。開発者がこの機能を使用する際に留意すべき重要な注意事項がいくつかあります。
- ' ' 演算子を使用してオブジェクトを比較すると、
==
プリミティブ型とオブジェクトに適用される可能性があるため、混乱を招く可能性があります。この演算子をオブジェクトに適用すると、実際にはオブジェクト自体ではなく、オブジェクトへの参照が比較されます。
public class Comparator {
public static void main(String[] args) {
Integer istInt = new Integer(1);
Integer secondInt = new Integer(1);
if (istInt == secondInt) {
System.out.println("both one are equal");
} else {
System.out.println("Both one are not equal");
}
}
}
- 等価演算子と関係演算子を使用して、オブジェクトとプリミティブ型を混合します。プリミティブ型をオブジェクトと比較すると、オブジェクトはボックス化されていないため、
NullPointerException
object がスローされる可能性がありますnull
。 - オブジェクトのキャッシュ。このメソッドは、
valueOf()
キャッシュするプリミティブ オブジェクトのコンテナを作成します。値は -128 ~ 127 の範囲でキャッシュされるため、これらのキャッシュされたオブジェクトは異なる動作をする可能性があります。 - パフォーマンスの低下。オートボックス化またはボックス化解除すると、ガベージ コレクターの実行頻度が高くなる不要なオブジェクトが作成されるため、アプリケーションのパフォーマンスが低下します。
public int sumEvenNumbers(List intList) {
int sum = 0;
for (Integer i : intList) {
if (i % 2 == 0) {
sum += i;
}
}
return sum;
}
コードのこのセクションでは、sum +=i
に展開されますsum = sum + i
。' ' 演算子はInteger オブジェクトに適用できない+
ため、JVM は ' ' 演算子からアンボックス化を開始します。+
そして、結果が自動パックされて戻されます。JDK 1.5 より前では、データ型int
と整数は異なりました。メソッドのオーバーロードの場合、これら 2 つのタイプは問題なく使用されました。自動梱包/開梱の登場により、これはさらに困難になりました。この例としてremove()
は、 のオーバーロードされたメソッドが挙げられますArrayList
。このクラスにはArrayList
2 つの削除メソッド (remove(index)
と )がありますremove(object)
。この場合、メソッドのオーバーロードは発生せず、対応するメソッドが適切なパラメーターを使用して呼び出されます。
結論
オートボクシングは、プリミティブ データ型を対応するラッパー クラス (オブジェクト) に暗黙的に変換するメカニズムです。コンパイラは、メソッドを使用してvalueOf()
プリミティブ型をオブジェクトに変換し、メソッドIntValue()
などをdoubleValue()
使用してオブジェクトのプリミティブ型を取得します。オートボクシングは、ブール型boolean
をブール型、byte
バイト型、char
文字型、 float
浮動小数点型、int
整数型、long
長型、short
短型に変換します。開梱は逆方向に行われます。 原著
GO TO FULL VERSION