Javaのintとbooleanのボックス化

Javaにおけるプリミティブ型のintとbooleanのボックス化メソッドについて少し調べてみた。

intのボックス化クラスとしてはInteger, booleanにはBooleanがjava.lang内に定義されている。

いずれにしても、明示的なボックス化の方法にはそれぞれのクラスのコンストラクタを呼ぶか、スタティックメソッドのvalueOfを呼ぶかの2つがある。Javaのドキュメンテーションによると、純粋なコンストラクタよりもvalueOfのほうが優先される的なことが書かれている。そこで、それぞれの実装がどうなっているのか、見てみることにする。

まず、整数型のIntegerクラスを見てみると、コンストラクタは普通に実装されている。
public Integer(int value) {
     this.value = value;
}
一方、valueOfメソッドは、ある限定的な範囲の整数を除いて、上記のコンストラクタを呼んでいる。int型に格納できる2^32通りのうちのほとんどの場合でこれらは凡そ等価である。ある限定的な範囲とは、下限は-128、上限はプロパティで指定された値か+127の大きい方である。この範囲の値が渡された場合には、Integerの内部に定義された内部クラスInteger.IntegerCacheに前もって作成されたオブジェクトの対応するものを返すようになっている。つまり、小さい整数はよく使われるのでキャッシュしておこうという話なのだろう。オブジェクトの生成は時間とメモリ領域を食うので、キャッシュを使ったほうが効率的である。なるほど。

次に、真偽値型のBooleanクラスを見てみた。Integerの場合と同じように、コンストラクタはまともに定義されている。ここまでは良い。一方で、Boolean.valueOf(boolean)メソッドは次のように定義されている。

public static Boolean valueOf(boolean b) {
     return (b ? TRUE : FALSE);
}

ここで、TRUEとFALSEは、Booleanクラス内のフィールドで、Booleanコンストラクタを使ってそれぞれtrueを表すBoolean型オブジェクト、falseを表すBoolean型オブジェクトとして初期化されている。そして、valueOfではそれらのオブジェクトを返しているというわけである。つまり、真偽値は所詮2通りしかないので、キャッシュも何も、それぞれについてstaticなオブジェクトを作っておいて、それを与えてやれば何の問題もない。したがって、booleanのボックス化はBoolean(boolean)コンストラクタを呼ぶ必要は全く無いのである。

プリミティブ型の明示的なボックス化は、それを使う頻度が多くあるかどうかは別として、コンストラクタよりもスタティックメソッドのvalueOfを呼んだほうが多くの場合効率が良いということが分かった。
なお、これはプリミティブ型がすでにあるときに有効であり、特殊な場合、例えば整数を10進以外でパースする場合などはまた別の話である。






いいなと思ったら応援しよう!