質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.32%

java ==演算子を使ったコードの実行結果について解説していただけないでしょうか。

解決済

回答 4

投稿

  • 評価
  • クリップ 1
  • VIEW 2,443

BSS_sapporo

score 40

現在、独学にてjavaを学んでいます。
以下の==演算子を使用したコードの実行結果を選択する問題が出題されたのですが、実行結果の一部が理解できません。
大変お手数ですが、以下のコードについて解説をお願いできますでしょうか。

class Test { 
  public static void main(String[] args) {
    Test t1 = new Test(10, "100") ;
    Test t2 = t1;
    Test t3 = new Test(10, "100");
    System.out.print((t1.getNo() == t3.getNo()) + " : ");
    System.out.print((t2.getId() == t3.getId()) + " : ");
    System.out.print(t1 == t3);
  }
  private int no;
  private String id;
  public Test(int n, String i) {
    no = n;
    id = i;
  }
  public int getNo() {
  return no;
  }
  public String getId() {
    return id;
  }
}

上記コードのSystem.out.print((t1.getNo() == t3.getNo()) + " :  ");ではint型データのため「同じ数値かどうか」を比較し 「true」 が出力され、
System.out.print((t2.getId() == t3.getId()) + " : ");ではString型データのため「同じ参照情報を持っているか」を比較し 「false」 が出力され、
System.out.print(t1 == t3);ではTest型データのため、String型データと同様に「同じ参照情報を持っているか」を比較し 「false」 が出力されると考えました。
(実行結果はtrue : false : false であると考えました。)

ですが、解答では

true : true : false

と出力される。と記載されており、どうやっても理解ができませんでした。

上記につきまして、初歩的な質問で申し訳ございませんが、どのように理解をするべきなのか、どこで解釈が間違っているのかを解説していただけないでしょうか。
何卒よろしくお願いいたします。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 4

+5

Javaでの==は確かに「オブジェクト同士の比較」ですが、文字列の場合はインターンといって、「(特にリテラルそのままの文字列の場合)別な箇所で生成した同じ内容の文字列が、同じオブジェクトを指す」ことが発生することもあります(イミュータブルなので、オブジェクト自体の属性を気にしないかぎり、他への影響はありません)。

言語によってはインターンしてくれることを保証する場合もあるのですが、Javaではそうなっていないので、同じ内容の文字列を==で比較した場合、「trueになるかfalseになるかはわからない」としか言えません。

Java で "1" == "1" が true になる理由

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/06/08 13:32

    ご回答ありがとうございます。
    trueになることもあればfalseになる場合もあるということなのですね。

    キャンセル

+2

(回答ではありませんが)
確かにこの場合true : true : falseと表示されるわけですが、だからといってこれを問題にしちゃいかんと思うのです。
他の方が指摘しているとおり、この問題に対する解答は「true : 不定 : false」 です。
だから文字列に対する==演算など(基本的には)やっちゃいかんのです。

オブジェクトの==演算をやっていいのは、enumやシングルトンの場合のみ。
イミュータブルは変更不可能である事は保証するが、同じ意味をもつオブジェクトが複数存在しないことは
保証しない。

よってこれは出題者のミスである。
・・・と私は思いますが如何でしょう?

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/06/08 19:38

    Javaにおいては、文字列リテラルはすべて`intern()`済みであることが言語仕様で決まっているので、(コードの書き方がわかりやすいかは別として)上記の場合であれば、2番目の比較は不定ではなく常に`true`になります。

    http://docs.oracle.com/javase/6/docs/api/java/lang/String.html#intern%28%29

    `intern()`済みの文字列オブジェクトを`==`演算子で比較するものもちろん問題ありません。(そもそも`intern()`とはそのためのメソッドなので)

    というわけで、Java言語においてはこのような出題については特に問題であるということはありません。(出題者の意図がそのような細かい部分の知識を問うているのかどうかはわかりませんが。。。)

    キャンセル

  • 2016/06/08 21:08

    これか・・・
    Moreover, a string literal always refers to the same instance of class String. This is because string literals - or, more generally, strings that are the values of constant expressions (§15.28) - are "interned" so as to share unique instances, using the method String.intern.
    確かに書いてありますね・・・
    >(しかし、出題者の意図がそのような細かい部分の知識を問うているのかどうかはわかりませんが。。。)
    という理由から、私はやはりこの設問は不適切だと思うのですよね。

    キャンセル

  • 2016/06/08 21:09

    ですが、勉強になりました。これはちゃんとJAVA仕様に書かれた動作なんですね。

    キャンセル

checkベストアンサー

0

文字列リテラルはメモリ節約のために、同一スコープ内で全く同じリテラルである場合、同じ参照になります。
ここに検証してるページがあります。
http://d.hatena.ne.jp/kota_seki/20120522/1337703851

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/06/08 13:36

    ご解説いただきありがとうございます。
    >文字列リテラルはメモリ節約のために、同一スコープ内で全く同じリテラルである場合、同じ参照になります。
    上記について初めて認識しました。
    今後、文字列リテラルの比較に==演算子が使われている場合(あまりないと思われますが)は注意したいと思います。

    キャンセル

0

String型に直接ダブルクォーテーションで囲った文字列を代入した場合、右辺は文字列リテラルとして扱われます。
この文字列リテラルはヒープ領域(newなどでメモリを確保する領域)ではなく
パーマネント領域(メソッドやクラス等の情報が配置される領域)という特殊な保存領域にメモリが取られます。
また、この場合、同一の文字列リテラル(今回で言うところの100)は1つのしか作成されないため、==で比較するとtrueになります。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/06/08 13:39

    ご回答いただきましてありがとうございます。
    特殊な保存領域の存在自体を存じ上げませんでした。
    大変助かりました。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.32%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る