オートボクシング |
Language の目次
|
Java プログラマなら誰でも知っていることですが、int
(またはその他のプリミティブ値) をコレクションに置くことはできません。コレクションはオブジェクト参照だけを保持できるため、プリミティブ値は適切なラッパークラス (int
の場合はInteger
) に「詰める (box)」必要があります。オブジェクトをコレクションから取り出すときは、格納した Integer
を取得します。int
が必要な場合は、intValue
メソッドを使用して、Integer
を「取り出す (unbox)」必要があります。これらはすべて煩しい操作であり、コードが複雑化します。オートボクシング / アンボクシング機能により、この処理が自動化され、余分な作業やコードの複雑さがなくなります。
次の例では、 汎用型および for-each ループを使用したオートボクシング / アンボクシング機能を示します。この 10 行足らずのコードで、コマンド行に現れる語の出現頻度を計算し、アルファベット順に出力します。
import java.util.*; // Prints a frequency table of the words on the command line public class Frequency { public static void main(String[] args) { Map<String, Integer> m = new TreeMap<String, Integer>(); for (String word : args) { Integer freq = m.get(word); m.put(word, (freq == null ? 1 : freq + 1)); } System.out.println(m); } } java Frequency if it is to be it is up to me to do the watusi {be=1, do=1, if=1, is=2, it=2, me=1, the=1, to=3, up=1, watusi=1}
まず、String
から Integer
へのマップを宣言し、コマンド行に出現する語の出現回数を関連付けます。次に、コマンド行の各語について反復処理を行います。それぞれの語について、マップ内で語を検索します。改訂した語のエントリをマップに入力します。この操作を行っている行 (緑色で強調表示) には、オートボクシング / アンボクシング機能の両方が含まれています。新しい値を計算して語に割り当てるには、まず現在の値 (freq
) を確認します。この値が null の場合は、今回が最初の出現になるため、マップに 1 を入力します。そうでない場合は、これまでの出現回数に 1 を足し、その値をマップに入力します。もちろん int
をマップに入力したり、Integer
に 1 を足すことはできません。実際は、freq
に 1 を足すためにオートボクシングが行われ、型 int
の式になります。条件式内の代替式の両方が型 int
であるため、この条件式自体も int
になります。この int
値をマップに入力するために、自動的に Integer
にボクシングします。
この操作全体の結果として、いくつかの注意点を除いて、int
と Integer
の区別をほとんど無視することができるのです。Integer
式では、null
値を使用できます。null をオートアンボックスしようとすると、NullPointerException
がスローされます。==
演算子は参照の同一性比較を Integer
式で実行し、値の等価性比較を int
式で実行します。最後に、閉じ込めおよび取り出しは自動的に行われますが、パフォーマンス上の負荷はかかります。
次に、オートボクシング / アンボクシング機能について、別のサンプルプログラムを示します。int
配列を取る static ファクトリであり、配列に基づく Integer
の List
を返します。この 10 行足らずのコードで、このメソッドは、int
配列の上位にある List
インタフェースの詳しい例を示します。リストに対するすべての変更は、配列に書き込まれます。逆も同様です。オートボクシング / アンボクシング機能の行は、緑色で強調表示されています。
// List adapter for primitive int array public static List<Integer> asList(final int[] a) { return new AbstractList<Integer>() { public Integer get(int i) { return a[i]; } // Throws NullPointerException if val == null public Integer set(int i, Integer val) { Integer oldVal = a[i]; a[i] = val; return oldVal; } public int size() { return a.length; } }; }
得られるリストのパフォーマンスは良くありません。これは、閉じ込めと取り出しが get
または set
操作ごとに行われるためです。このコードは、たまに使用するのであれば十分高速ですが、パフォーマンスが重要となる内部ループで使用することは避けてください。
オートボクシング / アンボクシング機能は、参照型とプリミティブとの間に「インピーダンス不整合」がある場合にだけ使用してください。たとえば数値をコレクションに入力しなければならない場合です。オートボクシング / アンボクシング機能を科学計算やパフォーマンスが重要な数値コードに使用することは、適切ではありません。Integer
は int
の代わりになりません。オートボクシング / アンボクシング機能により、プリミティブ型と参照型の区別があいまいになりますが、解消されるわけではありません。
Copyright © 2004 Sun Microsystems, Inc.All Rights Reserved. |
Java ソフトウェア |