Menu
Coddy logo textTech

instanceof 演算子

CoddyのJavaジャーニー「オブジェクト指向プログラミング」セクションの一部 — レッスン 31/87。

前のレッスンでは、オブジェクトが実際にはキャストしようとしている型ではない場合、ダウンキャストが ClassCastException で失敗する可能性があることを学びました。instanceof 演算子は、キャストする前にオブジェクトの型を確認できるようにすることで、この問題を解決します。

構文は単純です。object instanceof ClassName は、オブジェクトがそのクラス(またはそのサブクラスのいずれか)のインスタンスである場合に true を返します:

Animal animal = new Dog();

if (animal instanceof Dog) {
    Dog dog = (Dog) animal;
    dog.bark();  // Dog特有のメソッドを安全に呼び出すことができます
}

このチェックは、キャストが成功することを保証することで、実行時エラーを防ぎます。また、この演算子は階層内の親タイプに対しても 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);  // true

Java 16 以降、パターンマッチングを使用して、チェックとキャストを1つのステップで組み合わせることができます:

if (animal instanceof Dog dog) {
    dog.bark();  // 'dog' はすでにキャストされており、すぐに使用できます
}

このよりクリーンな構文により、個別のキャスト行が不要になります。instanceofnull に対してテストされた場合に false を返すため、個別の null チェックは不要であることに注意してください。

challenge icon

チャレンジ

簡単

instanceof 演算子を使用して、異なる車両タイプを安全に識別し、処理する車両検査システムを構築しましょう。車両の階層構造を作成し、各車両の実際のタイプを確認してから、そのタイプ固有の機能にアクセスするコードを記述します。

コードは4つのファイルに分けて構成します:

  • Vehicle.java: すべての車両が共有するベースクラスを作成します。すべての車両は model フィールド (String) を持ちます。これを初期化するためのコンストラクタ、ゲッターメソッド getModel()、および "Inspecting vehicle: " + model と出力する inspect() メソッドを含めてください。
  • Car.java: Vehicle を継承するクラスを作成します。Car は追加の numDoors フィールド (int) を持ちます。親クラスの初期化には super を使用してください。getModel() + " has " + numDoors + " doors" と出力する checkDoors() メソッドを追加します。
  • Motorcycle.java: Vehicle を継承する別のクラスを作成します。Motorcycle は hasSidecar フィールド (boolean) を持ちます。boolean 値に応じて、getModel() + " has a sidecar" または getModel() + " has no sidecar" のいずれかを出力する checkSidecar() メソッドを追加します。
  • Main.java: ここで instanceof が不可欠になります!車のモデル、ドアの数、バイクのモデル、およびサイドカーの有無 (true/false) の4つの入力を受け取ります。

    Car と Motorcycle を含む Vehicle 参照の配列を作成します。次に、配列をループして各車両に対して以下を行います:

    • ベースの inspect() メソッドを呼び出す
    • instanceof を使用して Car かどうかを確認し、そうであれば安全にダウンキャストして checkDoors() を呼び出す
    • instanceof を使用して Motorcycle かどうかを確認し、そうであれば安全にダウンキャストして checkSidecar() を呼び出す

4つの入力を受け取ります:車のモデル (String)、ドアの数 (int)、バイクのモデル (String)、およびサイドカーの有無 (boolean)。

出力は4行になります。各車両について、検査メッセージに続いてタイプ固有のチェック結果が表示されます。instanceof 演算子を使用することで、実際の Car に対してのみ Car のメソッドを、実際の Motorcycle に対してのみ Motorcycle のメソッドを呼び出すことが保証され、ClassCastException を防ぐことができます!

チートシート

instanceof 演算子は、キャストを行う前にオブジェクトが特定のクラスのインスタンスであるかどうかを確認します:

Animal animal = new Dog();

if (animal instanceof Dog) {
    Dog dog = (Dog) animal;
    dog.bark();  // Safe to call Dog-specific methods
}

この演算子は、オブジェクトのクラスおよび階層内のすべての親クラスに対して 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);  // true

Java 16 以降、パターンマッチングにより、確認とキャストを 1 つのステップで組み合わせることができます:

if (animal instanceof Dog dog) {
    dog.bark();  // 'dog' is already cast and ready to use
}

instanceof 演算子は、null に対してテストされた場合に false を返すため、個別の null チェックを行う必要がなくなります。

自分で試してみよう

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: 配列をループで回し、各車両に対して以下を行う:
        // 1. inspect() メソッドを呼び出す
        // 2. instanceof を使用して Car かどうかを確認し、そうであればダウンキャストして checkDoors() を呼び出す
        // 3. instanceof を使用して Motorcycle かどうかを確認し、そうであればダウンキャストして checkSidecar() を呼び出す
    }
}
quiz icon腕試し

このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。

オブジェクト指向プログラミングのすべてのレッスン