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

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

ただいまの
回答率

90.51%

  • Java

    15800questions

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

[==]と[equals]の挙動の違いを確認したい。

解決済

回答 3

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 830

sakuman0

score 9

前提・実現したいこと

[==]と[equals]の挙動の違いを確認したい。

発生している問題・エラーメッセージ

意図した動作にならない。

該当のソースコード

public class Main {
public static void main(String[] args){

Hero h1 = new Hero();
h1.name = "ミナト";
h1.hp = 100;

Hero h2 = new Hero();
h2.name = "ミナト";
h2.hp = 100;

if(h1.equals(h2) == true){
System.out.println("同じ内容です");
}else{
System.out.println("違う内容です");
}

if(h1 == h2){
System.out.println("同じ内容です");
}else{
System.out.println("違う内容です");

//以下Heroクラス
public class Hero {
String name;
int hp;

【出力結果】
違う内容です
違う内容です

補足情報(言語/FW/ツール等のバージョンなど)

ネットなどで確認する限りだと、
「==」はクラスに代入された値が同じであればtrueを表示。
「epuals」はメモリ上の保存位置まで同じであればtrueを表示。
と書いてあるように認識しました。

2つのインスタンスを使っているので、下がfalseになるのは分かるのですが、
全く同じ内容の上がfalseになるのはなぜでしょうか。
初歩的な内容で恐れ入りますが、ご教示頂けますでしょうか。

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 3

+4

「==」はクラスに代入された値が同じであればtrueを表示。 
「epuals」はメモリ上の保存位置まで同じであればtrueを表示。 

これはJavaではです。==は同一オブジェクトでだけtrueで、equalsは中身が等しければtrueです。

自分でクラスを作った場合、equalsで正しく判定してほしければ自分で実装する必要があります

なにもしない場合、Object.equalsリファレンス)が呼ばれて、「 x と y が同じオブジェクトを参照する (x == y が true) 場合にだけ true を返します。」

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2016/10/13 00:30

    ご回答有難う御座いました!

    色々理解がずれていたようなので、諸々再確認したのですが、
    以下のような理解であってますでしょうか。

    【解釈】
    まず、オブジェクトはインスタンスの属性が代入された状態だと再認識しました。
    ※<http://nobuo-create.net/java-beginner-17/&gt; 参照

    APIのequals説明を見ると、比較対象が同じオブジェクトを参照する場合に
    trueを表示と記載されていました。

    今回は「==」「equals」両方ともfalseと表示されたのですが、
    =========
    ・if(h1.equals(h2) == true){
    =========
    上記は、オブジェクトを「属性が代入されているインスタンス」だと理解すれば、
    h1とh2はメモリ上の別々の場所に保存されており、「違うインスタンス」となるので、
    代入後に「違うオブジェクト」となり、falseになると解釈しています。

    =========
    ・if(h1 == h2){
    =========
    こちらについてですが、「==」は内容さえ同じであればtrueのはずがfalseになるのが気になります。
    資料を模索して、以下のような解釈に至ったのですが、あってますでしょうか。

    ・「==」は変数に代入されている値にのみ有効。 newすると使えない。
    ・ オブジェクトを比較したいなら、「equals」を使うしかない。
      但し、内容が同じというだけだとfalseになる。
      
    http://javatechnology.net/java/if_string_equals/
    ※ちなみに上記の資料を参照して解釈しました。

    キャンセル

  • 2016/10/13 09:26

    Stringの場合は少し特殊で、「別な場所で作った同じ内容の文字列」が「同じオブジェクトになってしまう」ことがあります。ということで、Stringに==を使うと、同じ内容の文字列について、trueを返すこともfalseを返すこともあります。

    また、new Stringで文字列を生成することも可能です(リテラルで書けばいいので、ふつうは行いませんが)し、もちろんそれを==のオペランドにすることもできます。

    キャンセル

  • 2016/10/13 15:30

    参考書を進めていくとこれも少し載っているようでした。
    String型の比較には==ではなく、equalsを利用しないといけないのですね。
    次回以降質問をする際は、なるべく自己解決できるように、
    単元の区切り程度までは参考書を進めた上で質問するようにします。
    ご回答ありがとうございました。

    キャンセル

checkベストアンサー

+3

まだ回答を理解していないようですね。
まず基本的な話として、Javaにおいてはint,longなどのプリミティブ型以外はすべて参照型です。
参照型の変数にはその実体のオブジェクトが置かれている場所を示す値(参照値)が代入され、その値を使って実体にアクセスします。
以下はこれを理解した上で読んで下さい。

まず==は、両辺の変数が同じオブジェクトを指し示しているかどうかを判定する演算子です。内容がどうとかは全く判定しません。最も、同じオブジェクトを指していれば必然的に中身も同じですが。
newすると使えないわけではありません。ただし、そのnewしたオブジェクトと同じものを指す変数がほとんどの状況において存在しえないので、だいたいfalseになります。

equalsメソッドは、自分と引数として渡されたオブジェクトが「同じ」であるかどうかを判定するためのメソッドです。何をもって「同じ」とするかはクラスの設計者が決める必要があります。何も設計しなければ==での比較と全く同じ効果になります。設計に応じて、equalsメソッドをオーバーライドすることで、希望通りの比較ができるようになるのです。

例として出されたコードでは、2つのHeroオブジェクトを作り、名前をともに"ミナト"に設定し、HPを100に設定しました。しかしあくまでこれらのHeroは別個のオブジェクトです。別々のHeroに、同じ名前、同じHPを設定しただけで、別のものなのです。なので==での比較もfalseになるし、「同じ」の定義を==と一緒にしているequalsメソッドでもfalseになるのです。

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2016/10/13 15:24 編集

    非常に丁寧な回答有難う御座います。

    > まず==は、両辺の変数が同じオブジェクトを指し示しているかどうかを判定する

    ==の場合は、A書店に「JAVA入門書」という名称の本が2冊あったとして、
    店頭に置いてある本と奥に保管してある本は内容は同じですが、
    別々のオブジェクトなので違うもの(false)だと認識します、
    という考え方だと認識しました。

    > newすると使えないわけではありません。

    newすると中身は値ではなく案内板になるので、trueにするためには、
    比較対象の変数の中に同じ案内板が入っている必要がある。
    しかし、オブジェクト化している以上はそれぞれが別の実体であるはずなので、
    別の実体が同じメモリ格納先に入っているはずもなく、大概failsになると理解しました。
    ※ややこしい書き方になりすみません。

    > equalsメソッドは、自分と引数として渡されたオブジェクトが
    >「同じ」であるかどうかを判定するためのメソッドです。
    > 何をもって「同じ」とするかはクラスの設計者が決める必要があります。

    参考書のページを進めたらHeroクラスでObjectクラスの
    equalsメソッドをオーバーライドさせる話が載っていました。


    > (※equalsは)何も設計しなければ==での比較と全く同じ効果になります

    参考書などを見る限りでは、equalsメソッドは、比較対象オブジェクトの
    メモリ保管先が違ったとしても、内容さえ同じであれば、同一のものとみなすと書いてあり、
    同じ実体のみをtrueと捉える[==]とは逆になるように見受けられます。

    教えてもらっている中、些細な記載違いでしたら申し訳ありません。
    ====================================
    ※参考書を一部抜粋

    等価(equals)の判定
    さしている2つのものが「同じ内容」であること
    (同じアドレスを指していなくてもよい)

    Hero h1 = new Hero("ミナト"); メモリ:3345番地格納
    Hero h2 = new Hero("ミナト"); メモリ:9191番地格納

    このとき、h1 != h2 たが、
    h1.equals(h2)である。
    ====================================

    キャンセル

  • 2016/10/13 21:24

    2点目のnewについて
    newした際には「新たなオブジェクト」(この場合は本)が生成され、その新たなオブジェクトを指す案内板が返ってきます。これと別の変数とで"=="で比較してtrueになるためには両辺が同じ場所を指す案内板である必要があるわけですが、この場で新たに作ったオブジェクトを指す案内板がそれ以前に存在するはずがありません。よっぽど変な書き方をしない限り、newしたオブジェクトを"=="の比較の俎上に載せてtrueになることはありえません。

    ラストのequalsについて
    これはあくまでそういう比較のルール付け(すなわちequalsのオーバーライド)をしたあとでの話です。今のあなたのコードでは比較のルールを付けていない("=="での比較と同じ)ので、falseになります。

    キャンセル

  • 2016/10/14 00:14

    > この場で新たに作ったオブジェクトを指す案内板が
    > それ以前に存在するはずがありません。

    確かにその通りですね。
    非常に分かりやすいです。
    有難う御座います。


    > これはあくまでそういう比較のルール付け
    > (すなわちequalsのオーバーライド)をしたあとでの話です。

    失礼な質問をしてしまいすみません。
    参考書の抜粋は既にepualsがオーバーライドされていたんですね。
    APIにも「(※equalsは)比較対象が同じオブジェクトを参照する場合にtrueを表示」
    という感じの説明があったので、オーバーライド以前の挙動はどちらも
    「同一のオブジェクトを比較した場合にtrueと返す」と理解しました。

    この度は誠に有難うございました。

    キャンセル

+2

Heroクラスのequals()をoverrideしてあげていないからです。
Object#equals()の仕様はここに記載があります。

Effective Javaにある規約では、equalsをオーバーライドする時、次の内容を守るようにしろとの記載があります。

1.It is reflexive: For any reference value x, x.equals(x) must return true.
2.It is symmetric: For any reference values x and y, x.equals(y) must return true if and only if y.equals(x) return true.
3.It is transitive. For any reference values x, y, and z, if x.equals(y) returns true and y.equals(z) returns true, then x.equals(z) must return true.
4.It is consistent. For any reference values x and y, multiple invocations of x.equals(y) consistently return true or consistently return false, provided no information used in equals comparisons on the object is modified.

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2016/10/13 00:33

    ご回答ありがとうございます!
    equals を使う場合の true の判断基準はオーバーライドにより更新できる旨理解しました。
    詳細については、資料などから確認させていただこうと思います。

    キャンセル

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

  • Java

    15800questions

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