###等価と等値の違い
先日受けたJavaSilverの試験結果にて不正解と思われる箇所として
・「==とequals()を使用して文字列と他のオブジェクトが等しいかどうかをテストする」
が挙げられていたため、復習として記そうと思う。
参考[スッキリわかるJava入門](
|
public class Human {
String name;
int hp;
public String toString(){
return "name:" + this.name + "/age:" + this.age;
}
}
上記のとき、
等値
(==)の判定
「完全に同一の存在」=「同じアドレス値を指している」
Human h1 = new Human("Taro")
Human h2 = h1;
h2にh1を代入しているため、同じインスタンスA「name:Taro」をもち
参照先も同じ2112番地のアドレスを参照している。
このとき「h1 == h2」が成り立つ
等価
Human h1 = new Human("Ziro");
Human h2 = new Human("Ziro");
それぞれインスタンスを生成→参照している
インスタンスA「name:Ziro」 → 3322番地
インスタンスB「name:Ziro」 → 9191番地
「h1 != h2」が成り立つ
然し、文字列の内容は同じ
そのため「h1.equalsa(h2)」が成り立つ
うん、理解している。
が、
スッキリわかるJava入門を進めていて後半のAPI活用の章に入ると
equals()は「何をもって同じとするか」という評価基準を指定しないと正しく動かない、と記載があるのだがちょっと混乱する。
以下は正しく動作しない
例1)二人の人物を比べる
public class Main {
public static void main(String[] args) {
Human h1 = new Human();
h1.name = "Taro";
h1.age = 10;
Human h2 = new Human();
h2.name = "Taro";
h2.age = 10;
if ( h1.equals(h2) == true ) {
System.out.println("Same");
} else {
System.out.println("different") ;
}
}
}
Objectクラスから継承されるequals()の処理内容は以下の様に
「とりあえず等値ならtrueを返しとく」
という形になる
public boolean equals(Object o) {
if (this == o) {
return true;
} else {
return false;
}
}
「何を持って同じ内容とみなすか」はそれぞれのクラスにより異なるので、
それぞれで定義しなければならない
つまり「equalsをオーバーライド」して指定する
条件が「名前が同じなら、同じHumanとみなす」
なら下記のようになる
public class Human {
String name;
int age;
public boolean equals(Object o ) {
if (this == o) {
return true;
} if (o instanceof Human) { // 以下追加オーバーライド ①oをHuman型にキャストできるか判定
Human h = (Human)o; // ②Object型o をダウンキャストしてHuman型にし、hに代入
if ( this.name.equals(h.name)) {
return true;
}
}
return false;
}
}
「SAME」と表示される