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

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

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

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

Q&A

解決済

4回答

1628閲覧

Java 同一性確認について

Chandler_Bing

総合スコア673

Java

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

0グッド

1クリップ

投稿2020/02/29 13:49

以下オリジナルクラスについて比較結果です

java

1public class Sample { 2 3 int sample; 4 5 Sample(int sample) { 6 this.sample = sample; 7 8 } 9} 10 11public class Main { 12 13 public static void main(String[] args) { 14 // TODO 自動生成されたメソッド・スタブ 15 String hoge = "Hello"; 16 String fuga = "Hello"; 17 18 System.out.println(hoge == fuga);//1 true 19 System.out.println(hoge.equals(fuga));//2 true 20 21 Sample sample = new Sample(9) 22 Sample sample2 = new Sample(9); 23 24 System.out.println(sample == sample2);//3 flase 25 System.out.println(sample.equals(sample2));//4 flase 26 27 } 28 29}

まず私の認識についてあっているか教えていただきたいです。

「equals」による比較の結果は、オブジェクトに特段、equalsメソッドを記述していない場合は
単に右と左のオブジェクトが完全に一致していいるか比べるため4のような比較はfalseになる

まずこの認識自体はあっていますでしょうか。

上のような認識でいたため2、3と4の結果には納得できます。

しかしなぜ1もtrueになるのでしょうか。Stringはequalsで予め文字列が同じかで比較するというのが定義されていたかと思いますが、
その場合は「==」の評価判定も定義されている「equals」のそった評価をするのでしょうか。

確認に「hoge」と「fuga」の文字列を変更し別々のものにすると1と2共にfalseになりました。

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

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

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

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

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

guest

回答4

0

ベストアンサー

Stringプール

文字列リテラルだけが自動的にStringプールに登録され、プール内で唯一つのインスタンスを参照するようになっているから(FlyWeightパターン)。リテラル以外の文字列をプールに登録するには、Stringのintern()メソッドを呼びます。内部的には、文字列リテラルに.intern()を記述するのと同じ。

Java

1String hoge = "Hello".intern(); // intern()は自動的に行われます。 2String fuga = "Hello".intern();

intern()する際、同じ文字列がすでに登録されていれば、先に登録された参照値が使われます。

確認

つぎのメソッドを使います。

  • System#identityHashCode オーバーライドされていないオブジェクトの内部アドレスを返す。

intern()された文字列は同じ参照値になる

  • String#intern Stringをプールに登録する。プールには同じ文字列がただ一つ登録される。

つぎのStringのインスタンスが同じかどうかを確認します。

Java

1String hoge = "Hello"; 2String fuga = "Hello"; 3String fuge = "Hello".intern(); 4String interned = new String("Hello").intern(); 5String onHeap = new String("Hello");

確認してください。

Java

1System.out.println(System.identityHashCode(hoge)); 2System.out.println(System.identityHashCode(fuga)); 3System.out.println(System.identityHashCode(fuge)); 4System.out.println(System.identityHashCode(interned)); 5System.out.println(System.identityHashCode(onHeap));

String interned = new String("Hello").intern();宣言を先頭に持ってくると何が起きますか。

結論

==とは整数(参照値)の比較に他ならない。

Java

1hoge == fuga; 2System.identityHashCode(hoge) == System.identityHashCode(fuga);

equals()はオーバーライドされた動作。Stringのequals()は内部に保持する文字(配列)の内容が互いに一致するかを判定している。オーバーライドしなければObject#equalsの動作になる。それは、デフォルトの==比較である。

文字列リテラルはFlyweightパーターンに従う。つねに==が一致するゆえ内容equals()も一致する。

投稿2020/02/29 18:51

xebme

総合スコア1090

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

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

0

「equals」による比較の結果は、オブジェクトに特段、equalsメソッドを記述していない場合は単に右と左のオブジェクトが完全に一致していいるか比べるため4のような比較はfalseになる

まずこの認識自体はあっていますでしょうか。

Sampleクラスの基底クラス、Objectクラスの実装がそうなっていますから、そのとおりですね。

java

1public class Object { 2 3 public boolean equals(Object obj) { 4 return (this == obj); 5 } 6}

上のような認識でいたため2、3と4の結果には納得できます。

しかしなぜ1もtrueになるのでしょうか。Stringはequalsで予め文字列が同じかで比較するというのが定義されていたかと思いますが、その場合は「==」の評価判定も定義されている「equals」のそった評価をするのでしょうか。

java

1 String hoge = "Hello"; 2 String fuga = "Hello"; 3 System.out.println(hoge == fuga);//1 true 4 System.out.println(hoge.equals(fuga));//2 true

hoge, fugaはどちらも同じ"Hello"のインスタンス(リテラル)を参照しているので、==でもtrueとなります。

確認に「hoge」と「fuga」の文字列を変更し別々のものにすると1と2共にfalseになりました。

以下の結果も考えてみてください。

java

1 String hoge = "Hello"; 2 String fuga = new String("Hello"); 3 String piyo = fuga.intern(); 4 5 System.out.println(hoge == fuga);// false 6 System.out.println(hoge == piyo);// true 7 System.out.println(fuga == piyo);// false 8 System.out.println(hoge.equals(fuga));// true 9 System.out.println(hoge.equals(piyo));// true 10 System.out.println(fuga.equals(piyo));// true

投稿2020/02/29 14:22

shiketa

総合スコア4061

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

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

Chandler_Bing

2020/02/29 16:45

ありがとうございます。確かありましたねそんなの。 「equals」と「=」の比較対象の違いはなんなのでしょうか。
shiketa

2020/03/01 00:38

> そんなの # どんなのでしょうか? > 「equals」と「=」の比較対象の違いはなんなのでしょうか。 jimbeさんの回答にあるようにequals()メソッドは同値関係の実装です。 # 「=」は代入演算子です。 equals()メソッドと==演算子の違いは、「同一性 同値性」をキーワードにして訊いてみてください。
guest

0

同じ文字列リテラルは、同一オブジェクトになるからでしょう。

Java

1 String hoge = new String("Hello"); 2 String fuga = new String("Hello");

にすれば、あなたの予想通りになります。

投稿2020/02/29 14:20

otn

総合スコア85901

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

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

0

クラスObject - equals

Objectクラスのequalsメソッドは、もっとも比較しやすいオブジェクトの同値関係を実装します。つまり、null以外の参照値xとyについて、このメソッドはxとyが同じオブジェクトを参照する(x == yがtrue)場合にだけtrueを返します。

そして, 同じリテラル文字列はコンパイラによって(最適化の一環として)一つの文字列が流用されるでしょう.

投稿2020/02/29 14:15

編集2020/02/29 14:19
jimbe

総合スコア13209

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問