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

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

新規登録して質問してみよう
ただいま回答率
85.48%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Q&A

解決済

4回答

3094閲覧

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

BSS_sapporo

総合スコア44

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

4グッド

2クリップ

投稿2016/06/07 08:59

現在、独学にて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

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

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

stereo_code, tamy, RyotaKondo, ikuwow👍を押しています

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答4

0

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

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

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

投稿2016/06/07 09:07

maisumakun

総合スコア145183

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

BSS_sapporo

2016/06/08 04:32

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

0

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

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

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

投稿2016/06/08 10:06

KIshibashi

総合スコア42

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2016/06/08 10:38

Javaにおいては、文字列リテラルはすべて`intern()`済みであることが言語仕様で決まっているので、(コードの書き方がわかりやすいかは別として)上記の場合であれば、2番目の比較は不定ではなく常に`true`になります。 http://docs.oracle.com/javase/6/docs/api/java/lang/String.html#intern%28%29 `intern()`済みの文字列オブジェクトを`==`演算子で比較するものもちろん問題ありません。(そもそも`intern()`とはそのためのメソッドなので) というわけで、Java言語においてはこのような出題については特に問題であるということはありません。(出題者の意図がそのような細かい部分の知識を問うているのかどうかはわかりませんが。。。)
KIshibashi

2016/06/08 12: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. 確かに書いてありますね・・・ >(しかし、出題者の意図がそのような細かい部分の知識を問うているのかどうかはわかりませんが。。。) という理由から、私はやはりこの設問は不適切だと思うのですよね。
KIshibashi

2016/06/08 12:09

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

0

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

投稿2016/06/07 09:13

yona

総合スコア18155

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

BSS_sapporo

2016/06/08 04:39

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

0

ベストアンサー

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

投稿2016/06/07 09:04

masaya_ohashi

総合スコア9206

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

BSS_sapporo

2016/06/08 04:36

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問