- - PR -
AutoBoxingの仕様について
投稿者 | 投稿内容 | ||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
投稿日時: 2008-05-03 07:28
いつもお世話になっております。
現在、SJC-P5.0の資格取得に向けて勉強しておりますが、 AutoBoxing関連でわからない箇所がありましたので ご教授をお願いします。 尚、使用しているJDKは1.5.0_12 です。 まず、下記コードをコンパイルして実行したら結果はTrueが返ります。 class Test{ public static void main(String[] args){ Integer i = 10; Integer j = 10; if(i==j){ System.out.println("True"); }else{ System.out.println("False"); } } } しかし、INTEGERの部分を1234に変更するとFalseが返ってきます。 class Test{ public static void main(String[] args){ Integer i = 1234; Integer j = 1234; if(i==j){ System.out.println("True"); }else{ System.out.println("False"); } } } 今まではIntegerにint型を代入する際にはnew Integerとしてきましたが、 5.0からはAutoBoxing機能によってそのまま代入できるようになっております。 1234はint型の範囲に入っておりますので問題なく結果はTrueと推測しておりましたが、 実際の結果が違います。 なぜ、このような結果になるかご教授して頂けないでしょうか? よろしくお願いします。 | ||||||||||||||||
|
投稿日時: 2008-05-03 09:07
手前味噌ですがIntegerにはFlyweight が活きているあたりを参考に。
ボクシング変換で大量にIntegerオブジェクトを生成することになるため、 -128から127までの範囲でオブジェクトがキャッシュされるんです。 javadocにもキャッシュされる旨が書かれていますね。
| ||||||||||||||||
|
投稿日時: 2008-05-03 09:27
AutoBoxingでは「そのまま代入できる」わけではありません。
とした場合、実際には
が実行されます。AutoBoxing、つまり自動型変換ですね。 これはコンパイラが勝手にこうしたコードに置き換えてくれるわけで、 intにIntegerを、あるいはIntegerにintを「そのまま代入できる」わけではない。 細かな挙動を理解するにはこのあたりを注意しておく必要があります。 intとInteger間での型変換が自動でされるだけで、Integerはやはりオブジェクト型です。 ==での比較は、そのオブジェクトの参照の等しさを比較しますから、
とした場合、"False"が表示されます。 「問題なく結果はTrueと推測しておりました」とおっしゃっていますから オブジェクトの==比較とequals()による比較が混同されているように伺えます。 if (i==j)の部分は、Integer型同士の==比較です。 双方をint型に変換してからの==比較とはなりません。 そして、先に示したように、-128から127までの範囲では オブジェクトがキャッシュされるため、同一のインスタンスが用いられますから ==でオブジェクトの参照の等価性を見た場合にtrueになりますし、 その範囲外の場合はnew Integer()され、別のインスタンスが作られるためにfalseとなります。 | ||||||||||||||||
|
投稿日時: 2008-05-03 10:16
nagise様
早急なご回答ありがとうございます。 オブジェクトがキャシュされているなんて想像ができませんでした。 再度、AutoBoxingを見直しして自動変換であることと実際には 「Integer i = Integer.valueOf(10);」が実行されていることを 確認しました。 上記を確認した場合では確かにFalseになるのもうなずけます。 開発的には注意しないといけないと感じましたし、この辺で 不具合とかでそうな気がしております。 コード的には「Integer i = Integer.valueOf(10);」を記載した方が いいのかなぁ〜と実感しております。 ありがとうございます。 もっとJavaにのめり込んでいきます。 | ||||||||||||||||
|
投稿日時: 2008-05-03 12:19
Integer同士を==で比較する事自体が不具合の原因となります。 equalsで比較してください。これはAutoBoxingとは関係ありません。 逆に不具合の原因となりやすいのは逆のパターンです。
この場合、iに代入するときにNullPointerExceptionとなります。 | ||||||||||||||||
|
投稿日時: 2008-05-03 15:21
かつのり様
ご回答ありがとうございます。 確かに==では確認しないですよね 大変失礼しました。 class Test{ public static void main(String[] args){ Integer integer = null; int i = integer; } } 上記で確認を行い、NullPointerExceptionで確認しました。 でも開発的にはラッパーにしない方が無難と感じております。 | ||||||||||||||||
|
投稿日時: 2008-05-03 17:30
ListやMapとか使うと、自然とラッパー型を使わざるおえない状況になります。
という感じで、表には出ませんが、内部ではIntegerで格納されます。 とにかく、何が悪いだの使わない方がいいだのと、むやみに決めずに、 何をするとどうなるかをキチンと理解して使えば、副作用なしで使えます。 | ||||||||||||||||
|
投稿日時: 2008-05-03 23:34
SJC-Pを受けるという話が前提であるならば、Boxingの所はかなりマニアックな内容が出てきます。
したがって、合格を念頭に考えるのであれば、おそらく現在の理解でも問題ないでしょう。 Integerの-128から127までは〜なんて仕様は通常は意識しませんし、Javaを長くやっている開発者でもSJC−Pの勉強をした人か言語マニアでない限り、ずっと知らないままです。 ですが、== とequalsの違いは重要なのでしっかり学んでください。 ちなみに合格するにはBoxingよりもGenericsを深く学んだほうが高スコアが狙えると思います。 |