instanceof 演算子
CoddyのJavaジャーニー「オブジェクト指向プログラミング」セクションの一部。レッスン 31/87。
前のレッスンでは、オブジェクトが実際にはキャスト先の型でない場合、ダウンキャストが ClassCastException で失敗する可能性があることを示しました。instanceof 演算子を使うと、キャストする前にオブジェクトの型を確認できるため、この問題を解決できます。
構文は straightforward です。object instanceof ClassName は、object がその class(またはそのサブクラス)のインスタンスである場合に true を返します。
Animal animal = new Dog();
if (animal instanceof Dog) {
Dog dog = (Dog) animal;
dog.bark(); // Dog固有のメソッドを呼び出しても安全
}このチェックは、cast が成功することを確認して、実行時エラーを防ぎます。この演算子は、階層内の親型に対しても true を返します。
Dog dog = new Dog();
System.out.println(dog instanceof Dog); // true
System.out.println(dog instanceof Animal); // true
System.out.println(dog instanceof Object); // trueJava 16以降では、パターンマッチングを使用して、check と cast を1つのステップに組み合わせることができます。
if (animal instanceof Dog dog) {
dog.bark(); // 'dog' は既にキャスト済みで使用可能です
}このより簡潔な構文では、個別のキャスト行が不要になります。instanceof は null に対してテストすると false を返すため、個別に null チェックを行う必要はありません。
チャレンジ
簡単instanceof演算子を使用して、さまざまな車両タイプを安全に識別・処理する車両検査システムを構築しましょう。車両の階層を作成し、専用の機能にアクセスする前に各車両の実際のタイプを確認するコードを記述します。
コードを4つのファイルに分けて整理します。
Vehicle.java:すべての車両で共有する Baseclassを作成します。すべての車両にはmodelfield(String)があります。これを初期化するconstructor、getter methodgetModel()、そしてinspect()を出力するmethodInspecting vehicle: [model]を含めます。Car.java:Vehicleをextendsするclassを作成します。Carには追加のnumDoorsfield(int)があります。親のinitializationにはsuperを使用します。[model] has [numDoors] doorsを出力するmethodcheckDoors()を追加します。Motorcycle.java:Vehicleをextendsする別のclassを作成します。MotorcycleにはhasSidecarfield(boolean)があります。booleanの値に応じて、[model] has a sidecarまたは[model] has no sidecarのいずれかを出力するmethodcheckSidecar()を追加します。Main.java:ここでinstanceofが重要になります!4つのinputsを受け取ります。carのmodel、doorsの数、motorcycleのmodel、そしてsidecarがあるかどうか(true/false)です。CarとMotorcycleを含む
Vehiclereferencesのarrayを作成します。その後、arrayをLoopし、各vehicleについて次の処理を行います。- Baseの
inspect()methodをCallする instanceofを使用してCarかどうかをcheckする。Carの場合は、安全にdowncastしてcheckDoors()をCallするinstanceofを使用してMotorcycleかどうかをcheckする。Motorcycleの場合は、安全にdowncastしてcheckSidecar()をCallする
- Baseの
4つのinputsを受け取ります。carのmodel(String)、doorsの数(int)、motorcycleのmodel(String)、そしてhas sidecar(boolean)です。
出力には4行が表示されます。各vehicleについて、inspection messageに続いて、そのtype-specific checkが表示されます。instanceof operatorにより、実際のCarに対してのみCarのmethodsを、実際のMotorcycleに対してのみMotorcycleのmethodsをCallできるため、ClassCastExceptionを防止できます!
自分で試してみよう
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// 入力を読み取る
String carModel = scanner.nextLine();
int numDoors = Integer.parseInt(scanner.nextLine());
String motorcycleModel = scanner.nextLine();
boolean hasSidecar = Boolean.parseBoolean(scanner.nextLine());
// TODO: carModel と numDoors で Car オブジェクトを作成する
// TODO: motorcycleModel と hasSidecar で Motorcycle オブジェクトを作成する
// TODO: Car と Motorcycle を含む Vehicle 参照の配列を作成する
// TODO: 配列をループして各 vehicle について:
// 1. inspect() メソッドを呼び出す
// 2. instanceof を使って Car かどうかを確認し、ダウンキャストして checkDoors() を呼び出す
// 3. instanceof を使って Motorcycle かどうかを確認し、ダウンキャストして checkSidecar() を呼び出す
}
}
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。
オブジェクト指向プログラミングのすべてのレッスン
4継承
継承の基本 (extends)super キーワードメソッドのオーバーライド (@Override)コンストラクタチェーンObject クラス単一継承と多段階継承なぜ多重継承ができないのかまとめ:従業員の階層構造自分で練習してみよう: Javaオンラインコンパイラ