【Java】インスタンスの等価判定(前編) - たなかのJava日記
【Java】インスタンスの等価判定(後編) - たなかのJava日記
これまでにインスタンスの等価判定について学びました。
equals()をオーバーライドすることで、何をもって同じ内容かを決めることができました。
今回は、equals()をオーバライドする過程に存在した「instanceof演算子」について学びます。
【instanceof演算子とは】
構文:
変数 instanceof 型名
インスタンスが指定したクラスであるかどうかを判定してくれるキーワードです。
そのクラスで合っているかどうかを判定してくれます。
右オペランドが参照型の型名になります。 評価値の型はbooleanです。
左オペランド式が、右オペランドの型に代入可能な参照型の時、式の評価値が真(true)になります。
代入可能でない場合は偽になります。 別名「型比較演算子」とも言います。
【何のためにinstanceof演算子が存在するのか】
ダウンキャストを安全に行えるかを事前にチェックするためです。
ダウンキャストとは、あるクラスのサブクラスへと型を変換することです。
もう少し砕いた言い方だと「代入が失敗する可能性」を懸念してエラーを出すコンパイラに対して、
「大丈夫だから黙って代入しろ」と型変換を実行させる命令です。なので、コンパイルは成功します。
しかし、実際に動作させるとClassCastExceptionというエラーが発生する可能性があるのです。
これは、「キャストによる強制代入の結果、ウソだったよ!」と強制停止せざるを得ないという意味のエラーです。
equals()のオーバーライドする過程でも、キャストする場面がありますが、そこで強制停止する可能性があります。
その前に「instanceof演算子」でキャストする前に「キャストして大丈夫かどうか」のチェックを行っているということです。
package jp.co.mtanaka;
import java.util.ArrayList;
import java.util.List;
public class Sample2 {
public static void main(String[] args) {
List<Comedian> list = new ArrayList<>();
Comedian a = new Comedian();
a.name = "盛山";
list.add(a);
System.out.println("要素数" + list.size());
Comedian b = new Comedian();
b.name = "盛山";
list.remove(b);
System.out.println("要素数" + list.size());
}
}
package jp.co.mtanaka;
public class Comedian {
public String name;
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (!(obj instanceof Comedian)) {
return false;
}
Comedian c = (Comedian) obj;
if (!this.name.equals(c.name)) {
return false;
}
return true;
}
}
【まとめ】
Javaの全てのクラスはObject型を親クラスに持つので、Object型としてどんな引数も指定できる。
しかし、引数としてObject型で受けった実体は何のクラスかわからなくなります。
そこでinstanceofで「このクラスじゃないの?」とチェックすれば良い。
このチェックを行わずにキャストを行うと、コンパイルは通るが動作させるとClassCastExceptionというエラーが発生する可能性がある。
そのエラーを防ぐために、ダウンキャストを安全に行えるかを事前にチェックするために、「instanceof演算子」を使用する。
ちなみに、基本データ型はObjectを引数に取るメソッドには使用できません。
これは、基本型はObjectクラスを祖先に持っていないためです。
基本型を引数に取るには値をラッパークラスで包む(変換する)必要があります。
参考サイト:
Javaの型判定でのinstanceof演算子について徹底解説! | Javaコラム
java.lang.Stringクラスのequalsメソッドのソースコードを読んでみた