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

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

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

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

String

Stringは、ゼロ以上の文字から連続してできた文字の集合を扱うデータ型です。基本的にテキストを表すために使われます。

Q&A

解決済

3回答

4117閲覧

Java : ObjectクラスとStringクラスの { equals() }, { hashCode() } の違い

退会済みユーザー

退会済みユーザー

総合スコア0

Java

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

String

Stringは、ゼロ以上の文字から連続してできた文字の集合を扱うデータ型です。基本的にテキストを表すために使われます。

2グッド

0クリップ

投稿2018/05/17 08:29

不明点

現在OCJP Goldを学習中の初心者です。
ObjectクラスとStringクラスの動作で、どうしても理解ができない部分があったため、質問させていただきます。

Java

1public class Test { 2 public static void main(String[] args) { 3 String s1 = new String("A"); 4 String s2 = new String("A"); 5 6 System.out.println("s1.hashCode() : " + s1.hashCode()); 7 System.out.println("s2.hashCode() : " + s2.hashCode()); 8 System.out.println("s1 == s2 : " + (s1 == s2)); 9 System.out.println("s1.equals(s2) : " + s1.equals(s2)); 10 System.out.println(); 11 12 Object obj1 = new Object(); 13 Object obj2 = new Object(); 14 System.out.println("obj1.hashCode() : " + obj1.hashCode()); 15 System.out.println("obj2.hashCode() : " + obj2.hashCode()); 16 System.out.println("obj1 == obj2 : " + (obj1 == obj2)); 17 System.out.println("obj1.equals(obj2) : " + obj1.equals(obj2)); 18 System.out.println(); 19 } 20}

plain

1s1.hashCode() : 65 2s2.hashCode() : 65 3s1 == s2 : false 4s1.equals(s2) : true 5 6obj1.hashCode() : 2018699554 7obj2.hashCode() : 1311053135 8obj1 == obj2 : false 9obj1.equals(obj2) : false

このコードのなかで、それぞれのObjectクラスのインスタンスはnewされているため、ハッシュコードが異なり == でも { equals() } でもfalseになってしまうのは理解できます。
しかし、同様にStringクラスのインスタンスも互いにnewされているため、{ hashCode() } の返す値は異なると思うのですが、同じものになってしまう理由がわかりません。

調べてみようとしたものの、検索の能力が低く、ObjectクラスとStringクラスのそれぞれのメソッドの動作差について見つけることができなかったため、こちらにて質問させていただきます。

拙い文章で申し訳ないですが、よろしくお願いします。

terrace, yohhoy👍を押しています

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

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

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

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

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

guest

回答3

0

ハッシュコードは、equalsでtrueになる(=等しいと判定される)オブジェクトが同じ値を返すよう設計されており、またそうするよう規定されています。
newされた2つのStringはモノとしては異なるもののため、==ではfalseになりますが、同じ"A"を表す等しいオブジェクトであるため、equalsではtrueとなります。

投稿2018/05/17 08:40

編集2018/05/17 08:41
swordone

総合スコア20651

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

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

0

ベストアンサー

同様にStringクラスのインスタンスも互いにnewされているため、{ hashCode() } の返す値は異なると思うのですが

この部分が誤りです。Stringequalsで内容を比較するように実装してありますが、「equalsで等しくなるものは同じhashCodeを返さないといけない」というルールがありますので(Oracle)、必然的に同じ内容の文字列のhashCodeは同じ値を返します(そのように実装されています)。

投稿2018/05/17 08:36

maisumakun

総合スコア145183

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

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

退会済みユーザー

退会済みユーザー

2018/05/18 00:10

equalsとhashCodeの相互関係について、一番わかりやすく理解できたためベストアンサーとさせていただきます。 回答ありがとうございました!
guest

0

Stringクラスのインスタンスも互いにnewされているため、{ hashCode() } の返す値は異なると思うのですが、同じものになってしまう

GrepCodeでStringクラスのソースを確認してみました。

122 private int hash; // Default to 0

↑まず、hashCodeの算出に使用されるフィールド「hash」は初期値0です。

192 public String(char value[]) { 193 int size = value.length; 194 this.offset = 0; 195 this.count = size; 196 this.value = Arrays.copyOf(value, size); 197 }

↑次に、フィールド「offset」「count」「value」について、与えられた文字列が同じ値の文字列である限り、同一の値を持つことが分かります。

1493 public int hashCode() { 1494 int h = hash; 1495 if (h == 0) { 1496 int off = offset; 1497 char val[] = value; 1498 int len = count; 1499 1500 for (int i = 0; i < len; i++) { 1501 h = 31*h + val[off++]; 1502 } 1503 hash = h; 1504 } 1505 return h; 1506 }

↑メソッド「hashCode()」では、フィールド「hash」「offset」「count」「value」の値をもとに戻り値を算出するので、同値の文字列から生成された複数インスタンスでは、常に同値のハッシュコードが得られる、となります。

{ equals() }

「equals()」の挙動についても見てみると、

1012 public boolean equals(Object anObject) { 1013 if (this == anObject) { 1014 return true; 1015 } 1016 if (anObject instanceof String) { 1017 String anotherString = (String)anObject; 1018 int n = count; 1019 if (n == anotherString.count) { 1020 char v1[] = value; 1021 char v2[] = anotherString.value; 1022 int i = offset; 1023 int j = anotherString.offset; 1024 while (n-- != 0) { 1025 if (v1[i++] != v2[j++]) 1026 return false; 1027 } 1028 return true; 1029 } 1030 } 1031 return false; 1032 }

↑同一インスタンスでない場合に、比較対象がStringインスタンスの時、フィールド「value」の各要素の値比較を行い、その結果を返す仕様であることが分かります。

投稿2018/05/17 08:55

tkturbo

総合スコア5572

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

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

退会済みユーザー

退会済みユーザー

2018/05/17 09:24

随分古いソースだと思ったらJava6ですか。Java8からはoffsetとcountはありません。Java9からvalueはchar[]ではなくてbyte[]になっています。すみません。この回答の趣旨とはあまり関係ない話でした。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問