ボックス化とは
プログラミングにおける
ボックス化(boxing)とは、値型をオブジェクト型(参照型)に変換する操作です。この逆の操作、つまりボックス化されたオブジェクトを値型に戻すことは
ボックス化解除(unboxing)と呼ばれます。
概要
Javaや
.NET Frameworkなどの環境では、整数や
浮動小数点数などの値型と、オブジェクトなどの参照型という、根本的に異なる2種類の型が存在します。参照型はヒープ領域に、値型はスタックや他の参照型の一部としてメモリ上に確保されます。
異なる性質を持つ値型と参照型ですが、値型をオブジェクト型として扱いたい場面が多々あります。例えば、
Javaではプリミティブ型(int, floatなど)はオブジェクトではなく、
コレクションに直接格納できません。そのため、プリミティブ型をオブジェクトとして包む(ラッピング)必要があり、この処理がボックス化です。
Javaでは、各プリミティブ型に対応するラッパークラス(`Integer`, `Float`など)が用意されています。
以下は
Javaでの例です。
java
int primitiveInt = 10;
Integer boxedInt = Integer.valueOf(primitiveInt); // ボックス化
int unboxedInt = boxedInt.intValue(); // ボックス化解除
ボックス化では、ヒープ領域に新しいオブジェクトが作成され、そこに値型のデータがコピーされます。このため、頻繁なボックス化はパフォーマンス低下の原因となります。一方、ボックス化解除はデータのコピーのみで済むため、コストは比較的小さいです。
ボックス化における注意点
ボックス化は、単なる
型変換に見えますが、実際にはヒープ領域の確保とデータのコピーが発生します。特に、頻繁なボックス化はパフォーマンスに悪影響を及ぼす可能性があります。
また、`Integer.Integer(int)`コンストラクタよりも、`Integer.valueOf(int)`メソッドの使用が推奨されます。これは、よく使用される数値に対しては、ラッパーオブジェクトのキャッシュを優先的に利用するためです。
関数型言語におけるボックス化
関数型言語にもボックス化の概念が存在しますが、オブジェクト指向のそれとは異なります。関数型言語でのボックス型は、単なる
間接参照として扱われます。
Haskellのような言語では、非ボックス型(Unboxed type)を明示的に指定しないと、ボックス化された型が使用されます。`IO`型などがその典型例です。
自動ボックス化
ボックス化とボックス化解除を暗黙的に行うことを
自動ボックス化(autoboxing)および
自動ボックス化解除(auto-unboxing)と呼びます。
Javaでは、
Java SE 5から自動ボックス化が導入され、プリミティブ型とラッパークラス間の変換が
コンパイラによって自動的に行われるようになりました。
以下は
Javaでの自動ボックス化の例です。
java
Integer boxedInt = 10; // 自動ボックス化
int primitiveInt = boxedInt; // 自動ボックス化解除
.NETにおけるボックス化
.NETでは、全ての型が`System.Object`型から派生しているため、値型も暗黙的に`System.Object`型にアップキャストできます。これは
Javaの自動ボックス化に相当します。一方、ボックス化解除はダウンキャストによって明示的に行う必要があります。
C#での例を以下に示します。
csharp
int valueTypeInt = 10;
object boxedInt = valueTypeInt; // ボックス化
int unboxedInt = (int)boxedInt; // ボックス化解除
Javaでは、
配列以外の
コレクション(`ArrayList`, `LinkedList`など)には参照型しか格納できません。そのため、プリミティブ型のデータを
コレクションに格納する際には、対応するラッパークラスのオブジェクトにボックス化する必要があります。取り出す際には、ダウンキャストしてからボックス化解除します。
Java 1.5以降では、ジェネリクスと自動ボックス化により、プリミティブ型のデータをオブジェクトのように扱うことができますが、内部的にはボックス化とボックス化解除は依然として行われています。ただし、ジェネリクスは型安全性を保証するだけであり、パフォーマンス上の優位性はありません。
.NETでは、.NET 1.1までは
Javaと同様にボックス化が必要でしたが、.NET 2.0以降のジェネリクスでは値型を直接扱うことができるため、ボックス化は発生しません。
まとめ
ボックス化は、値型と参照型の異なる型を連携させるために重要な概念です。
Javaや.NETなどの環境では、頻繁に利用される機能であるため、その仕組みを理解することで、より効率的なプログラミングを行うことができます。自動ボックス化は便利な機能ですが、パフォーマンスへの影響も考慮する必要があります。