Stringのequalsと==の違い復習

クラスStringはObjectのequalsメソッドをオーバーライドしている。

クラスObjectのequalsメソッドは単に==をしているだけ。

//	Objectのezualsメソッド
public boolean equals(Object obj) {
  return (this == obj);
}

クラスStringや他のラッパークラスはequalsをオーバーライドしている。

==の結果がfalseでも同じ値を持ったオブジェクトならtrue

//	Stringのequalsメソッド
public boolean equals(Object anObject) {
  if (this == anObject) // ここがfalseでも、
  {/* ... */}
  if (anObject instanceof String) {
  /*  両者の文字列を一文字ずつ順番に比べて行き、 */
  /*  falseが出なければreturn true; */
  }
}

実際に比べてみる

String strQ1 = "hello";
String strQ2 = "hello";
String strNew1 = new String("hello");
String strNew2 = new String("hello");

// strQ1とstrQ2は同じオブジェクトを参照している
// (文字列リテラルはinternされ既存の場合それとインスタンスを参照する)
System.out.println(strQ1==strQ2); // true
System.out.println(strQ1.equals(strQ2)); // true

// strNew1とstrNew2は別々のオブジェクトを参照している
System.out.println(strNew1==strNew2); // false
// しかしequalsは同じ文字列を保持していれば違うオブジェクトでもtrue
System.out.println(strNew1.equals(strNew2)); // true

// これも違うオブジェクトをそれぞれ参照している
System.out.println(strQ1==strNew1);	// false
// でも同じ文字列を保持しているのでequalsで比べるとtrue
System.out.println(strQ1.equals(strNew1)); // true

コンパイル時に計算されるものと実行時にされるものの違い

String hello = "Hello", lo = "lo";

// 定数式によって生成される文字列はコンパイル時に計算されリテラル扱い
System.out.print((hello == ("Hel"+"lo")) + " "); // true
// 実行時に計算される文字列は新たに生成されるので別物に
System.out.print((hello == ("Hel"+lo)) + " "); // false
// intern()は同じ内容をもつ既存のリテラル文字列を返す(※あった場合)
System.out.println(hello == ("Hel"+lo).intern());