コンピュータサイエンスにおいて、ボクシング(ラッピングとも呼ばれる)とは、プリミティブ型をオブジェクト内に配置して、その値を参照として使用できるようにする変換のことです。アンボクシングとは、プリミティブ値をラッパーオブジェクトから取り出す逆の変換です。オートボクシングとは、必要に応じてボクシングやアンボクシングの変換を自動的に適用することを意味します。
ボクシングの最も顕著な使用例はJavaで、実行時の効率や構文と意味の問題などの理由から、参照型と値型が区別されています。Java では、は のインスタンスである必要があります。 を持ちたいと思うかもしれませんが、これは直接はできません。代わりに、Java は各プリミティブ型に対応するプリミティブ ラッパー クラス( 、、、、など) を定義します。Java Platform, Standard Edition (J2SE) 5.0 で導入された汎用パラメータ化型を使用すると、を定義し、値をオブジェクトとしてボクシングすることでリストに値を挿入できます。LinkedList<T>TObjectLinkedList<int>IntegerintCharactercharFloatfloatLinkedList<Integer>intInteger
一方、C#にはプリミティブ型のラッパークラスはありませんが、任意の値型をボックス化して汎用Object参照を返すことができます。Objective -Cでは、任意のプリミティブ値に をプレフィックスとして付けることで、それを にすることができます (例:@または) 。これにより、 を などの標準コレクションに追加することができます。NSNumber@123@(123)NSArray
Haskellには参照型の概念はほとんど、あるいは全くありませんが、ランタイムシステムの統一されたタグ付き共用体へのポインタ表現に対しては「boxed」という用語を使用しています。[ 1 ]
ボックス化されたオブジェクトは常に値オブジェクトのコピーであり、通常は不変です。オブジェクトのアンボックス化でも、格納された値のコピーが返されます。オブジェクトのボックス化とアンボックス化を繰り返すと、ボックス化によって新しいオブジェクトが動的に割り当てられ、アンボックス化(ボックス化された値が使用されなくなった場合)によってガベージコレクションの対象となるため、パフォーマンスに深刻な影響を与える可能性があります。ただし、Java HotSpot ガベージコレクタなどの最新のガベージコレクタは、短命なオブジェクトをより効率的に収集できるため、ボックス化されたオブジェクトの寿命が短い場合は、パフォーマンスへの影響はそれほど深刻ではない可能性があります。
一部のプログラミング言語では、ボックス化されていないプリミティブ型と、不変のボックス化されたオブジェクト型への参照との間に直接的な等価性があります。実際、プログラム内のすべてのプリミティブ型をボックス化されたオブジェクト型に置き換えることが可能です。あるプリミティブ型から別のプリミティブ型への代入では値がコピーされますが、ボックス化されたオブジェクトへの参照から別の参照への代入では、参照値がコピーされ、最初の参照と同じオブジェクトを参照するようになります。ただし、オブジェクトは不変であるため、同じオブジェクトへの参照と異なるオブジェクトへの参照の間には意味的に実質的な違いはなく(物理的な等価性を考慮しない限り)、問題は発生しません。代入以外のすべての操作(算術演算、比較演算、論理演算子など)については、ボックス化された型をボックス化解除し、演算を実行して、必要に応じて結果をボックス化することができます。したがって、プリミティブ型をまったく格納しないことも可能になります。
オートボクシングとは、型変換(暗黙的または明示的)のみによって値型から参照型を取得することを指します。コンパイラは、オブジェクトを作成するための追加のソースコードを自動的に提供します。
例えば、J2SE 5.0より前のバージョンのJavaでは、以下のコードはコンパイルされませんでした。
Integer i = new Integer ( 9 ); Integer i = 9 ; // 5.0 より前のバージョンではエラーになります!5.0 より前のコンパイラでは、最後の行は受け入れられませんでした。は参照オブジェクトであり、表面上は 、 などと変わりません。からに変換するには、Integer オブジェクトを「手動で」インスタンス化する必要がありました。 J2SE 5.0 以降では、コンパイラは最後の行を受け入れ、値 を格納する Integer オブジェクトが作成されるように自動的に変換します。[ 2 ]これは、J2SE 5.0 以降では、と自体であるのようながコンパイルされることを意味します。a と b はアンボックス化され、整数値が合計され、結果が新しい に自動的にボックス化され、最終的に変数 に格納されます。等価演算子は、参照の等価性のために参照型に対して既に定義されているため、この方法では使用できません。ボックス化された型の値の等価性をテストするには、手動でアンボックス化してプリミティブを比較するか、メソッドを使用する必要があります。IntegerListObjectintInteger9Integerc=a+babIntegerIntegercObjects.equals
別の例として、J2SE 5.0 では、プログラマーがコレクション ( など) をオブジェクトではなく値を含むものとして扱うことができます。これは、上記の説明と矛盾しません。コレクションには依然として動的オブジェクトへの参照のみが含まれており、プリミティブ型をリストすることはできません。 にはなれませんが、 でなければなりません。ただし、コンパイラーはコードを自動的に変換し、ソースコードではプリミティブ値のみに言及しているにもかかわらず、リストが「黙って」オブジェクトを受け取るようにします。たとえば、プログラマーはがリストに追加されたかのように記述して考えることができますが、実際にはコンパイラーは を に変換します。LinkedListintIntegerLinkedList<int>LinkedList<Integer>list.add(3)int3list.add(newInteger(3))
自動アンボクシングでは、コンパイラは、そのオブジェクトのメソッドを呼び出すか、その他の方法によって、そのオブジェクトから値を取得するための追加のソースコードを自動的に提供します。
例えば、J2SE 5.0より前のバージョンのJavaでは、以下のコードはコンパイルされませんでした。
Integer k = new Integer ( 4 ); int l = k.intValue ( ); // 常に問題なしint m = k ; //エラーになるはずだったが、今は問題なしC# は Java と同じ意味での自動アンボクシングをサポートしていません。なぜなら、C# にはプリミティブ型とオブジェクト型の明確な区別がないからです。Java ではプリミティブ型とオブジェクト型の両方が存在するすべての型は、C# コンパイラによって自動的にプリミティブ型(値型)またはオブジェクト型(参照型)として実装されます。
どちらの言語でも、自動ボクシングでは自動的にダウンキャストは行われません。つまり、次のコードはコンパイルされません。
C#:
int i = 42 ; object o = i ; // ボックスint j = o ; // アンボックス (エラー) Console.WriteLine ( j ); // 到達不能な行。作成者は「42」という出力を期待していた可能性があります。Java:
int i = 42 ; Object o = i ; // ボックスint j = o ; // アンボックス (エラー) System.out.println ( j ); // 到達不能な行。著者は出力「42」を期待していた可能性があります。RustBoxには、一意に所有され、ヒープに割り当てられた値を表す型があります。 [ 3 ]
let number : Box <i32> = Box :: new ( 42 ) ;std::boxed::BoxRust の はC++std::unique_ptrのに相当し、一種のスマートポインタです。
std :: unique_ptrを使用します。unique_ptr <int> number = std :: make_unique <int> ( 42 ) ;値の所有権を共有する必要がある場合(たとえば、スレッド間)、Arc参照カウントされたヒープ割り当て値を表す を使用できます。[ 4 ] [ 5 ]std::shared_ptrこれはC++ のに似ています。
現代のオブジェクトパスカルには、単純な型に対して操作を実行するための別の方法があり、これはボクシングに近いもので、Free Pascalでは型ヘルパー、 DelphiおよびFree Pascal in Delphiモードではレコードヘルパーと呼ばれます。
ここで挙げた方言はObject Pascalからネイティブ言語にコンパイルされる言語であるため、C#やJavaが実装できる一部の機能が欠けている。特に、厳密に型付けされた変数に対する実行時型推論が欠けている。
ただし、この機能はボクシングに関連しています。次のような構造を使用できます。
{$ifdef fpc}{$mode delphi}{$endif} uses sysutils ; // このユニットには単純型のラップが含まれていますvar x : integer = 100 ; s : string ; begin s := x . ToString ; writeln ( s ) ; end .