ミラーサイト作りました。今後はそちらをメインにするかも知れません。よろしくお願いします。

あれこれ備忘録 〜はてなブログ支店〜

もしもドロップシッピング」で販売サイト作ってみました。
あれこれ商店

画期的な無料家計簿アプリでお金の流れが一目で分かる

2011年07月27日

オートボクシングの落とし穴

Integer i1 = 1;
Integer i2 = 1;
Integer i3 = 1000;
Integer i4 = 1000;
System.out.println(i1 == i2);
System.out.println(i3 == i4);


これは最初のprintlnはtrueになり、二つ目の出力はfalseになります。

何故でしょう。

それはオートボクシング(auto-boxing)という機能のせいだそうです。

javaはオブジェクト指向のプログラミング言語ですが、すべてをオブジェクトとして扱うとパフォーマンスの低下を招くなどの理由でintなど一部の変数の型としてプリミティブ型というオブジェクトではない型の変数を扱えるようにしてあります。
byte・short・int・long・float・double・char・booleanがプリミティブ型です。

これをオブジェクトとして扱うときにはint型の場合、
Integer intObj1 = new Integer(100);
Integer intObj2 = Integer.valueOf(2);


などといった形で100や2の値を持つIntegerクラスのオブジェクトを作って、これを例えばリストに格納したりします。

しかし、結構これは面倒です。

これを使ってもう一度整数の値として取り出して、計算などに使おうと思ったときには

int primitiveInt1 = intObj1.intValue();


などとします。

別のInteger型の変数に値だけ代入する場合には、

intObj2 = Integer.valueOf(intObj2.intValue());


これを計算で必要になる度にするのは面倒ですよね。

これを

intObj2 = primitiveInt1


のようにできるのがオートボクシング機能です。


しかし、これが落とし穴になるらしいのです。
もう一度見てみましょう。

Integer i1 = 1;
Integer i2 = 1;
Integer i3 = 1000;
Integer i4 = 1000;
System.out.println(i1 == i2);
System.out.println(i3 == i4);



(i1 == i2)はtrueになるのに、(i3 == i4)はfalseになる。

これは何故か。

実は、そもそも(i1 == i2)も本来はfalseになるはずなのです。

(i1 == i2)というのはi1というオブジェクトとi2というオブジェクトは同じか?という判定を行っています。

i1とi2は別のオブジェクトなので本来はfalseなのですが、オートボクシングが効くとキャッシュされたIntegerが使われるそうで、

最初の

Integer i1 = 1


のときに、Integer.valueOf(1)で作られて返されたInteger型がキャッシュされていて、i2についても同じように定義されているので、このキャッシュされたものが使われるらしいのです。

だからこの場合、i1とi2は同じオブジェクトになるということです。

では、もう一方の(i3 == i4)はどうかというと、キャッシュが効く範囲がintの場合、-128から127なのでその範囲外の場合は別のオブジェクトとして定義されてしまいます。

その結果、(i3 == i4)はfalseになるのですね。


そういえば、今はどうか分かりませんが、以前はjavaの高速化手法として-128から127の範囲では

i++


よりも

i = i + 1


のほうが高速であるというのがありました。これはJVMで動くバイトコードが違うからだったと思います。


さて、もとの問題ですが、そもそも==をこの様に使うのは問題なので

i1.equals(i2);


のようにすると値を比較する方法としては正しく動きます。


Javaパフォーマンステクニック―サーバサイドプログラミングの最適化 (Java Performance and Scalability Vo)

Javaパフォーマンス戦略―高速プログラムの高速開発のためのイディオム集

Javaプラットフォームパフォーマンス―コードレベルのチューニングと開発プロセスへの統合 (The Java Series)

プロフェッショナルAndroidゲームプログラミング JavaとCによるハイパフォーマンスなゲームの作り方

posted by まっさん at 20:41 | Comment(0) | java | このブログの読者になる | 更新情報をチェックする
この記事へのコメント
コメントを書く
お名前: [必須入力]

メールアドレス:

ホームページアドレス:

コメント: [必須入力]


iPagerank ブログランキング・にほんブログ村へ
にほんブログ村 ランキングはこちらをクリック!

×

この広告は1年以上新しい記事の投稿がないブログに表示されております。