🎯

【Java】クラス解説25・instanceof演算子

2024/01/24に公開

instanceof演算子について

instanceof演算子は、ある変数がどのクラスのインスタンスを保持しているかどうかを確認するのに使います。

instanceof演算子のコード例1

public class Main {
    public static void main(String[] args) {
        Fuzi f1 = new Fuzi();
        // instanceof演算子
        System.out.println(f1 instanceof MyClass); // 出力結果 -> true
        System.out.println(f1 instanceof Fuzi); // 出力結果 -> true
    }
}

class MyClass {}
class Fuzi extends MyClass {}

コード例の解説

class MyClass {}
class Fuzi extends MyClass {}
  1. MyClassクラスを定義します。
  2. MyClassを継承したFuziクラスを定義します。

コード例1の解説

public class Main {
    public static void main(String[] args) {
        Fuzi f1 = new Fuzi();
        System.out.println(f1 instanceof MyClass); // 出力結果 -> true
        System.out.println(f1 instanceof Fuzi); // 出力結果 -> true
    }
}

Mainクラスで、

  1. Fuziクラスのインスタンスを持つ変数f1を定義します。
  2. 変数f1がMyClassクラスのインスタンスを持つかどうかを標準出力に出力します。出力結果はtrueとなります。
  3. 変数f1がFuziクラスのインスタンスを持つかどうかを標準出力に出力します。出力結果はtrueとなります。

instanceof演算子のコード例2

public class Main {
    public static void main(String[] args) {
        Fuzi f1 = new Fuzi();
        MyClass mc = f1;
        // Sakura s = (Sakura) mc; // コンパイルエラー
        
        System.out.println(mc instanceof MyClass); // 出力結果 -> true
        System.out.println(mc instanceof Fuzi); // 出力結果 -> true
        System.out.println(mc instanceof Sakura); // 出力結果 -> false
    }
}

class MyClass {}
class Fuzi extends MyClass {}
class Sakura extends MyClass {}

コード例2の解説

class MyClass {}
class Fuzi extends MyClass {}
class Sakura extends MyClass {}
  1. MyClassクラスを定義します。
  2. MyClassを継承したFuziクラスを定義します。
  3. MyClassを継承したSakuraクラスを定義します。

public class Main {
    public static void main(String[] args) {
        Fuzi f1 = new Fuzi();
        MyClass mc = f1;
        // Sakura s = (Sakura) mc; // コンパイルエラー
        
        System.out.println(mc instanceof MyClass); // 出力結果 -> true
        System.out.println(mc instanceof Fuzi); // 出力結果 -> true
        System.out.println(mc instanceof Sakura); // 出力結果 -> false
    }
}

Mainクラスで

  1. Fuziクラスのインスタンスを持つ変数f1を定義します。
  2. MyClass型の変数mcに、Fuziクラスのインスタンスを持つ変数f1を代入します。
    (アップキャスト)
  3. Sakura型の変数sに、Sakuraクラスにダウンキャストした変数mcを代入します。
    しかし、変数mcはFuziクラスのインスタンスを保持しており、FuziクラスとSakuraクラスは継承関係にないためにコンパイルエラーとなります。
    なお、当該行は、コンパイルエラーとなるためコメントアウトしています。
  4. 変数mcがMyClassクラスのインスタンスを持つかどうかを標準出力に出力します。出力結果はtrueとなります。
  5. 変数mcがFuziクラスのインスタンスを持つかどうかを標準出力に出力します。出力結果はtrueとなります。
  6. 変数mcがSakuraクラスのインスタンスを持つかどうかを標準出力に出力します。出力結果はfalseとなります。 falseの理由は、3.の通りです。

コンパイルエラーを避けるためのコード例

先程の「instanceof演算子のコード例2」では、コンパイルエラーが起こってしまうので、後の処理に進まなくなってしまいます。そのため、下記のように、ダウンキャストを行う前に、そのインスタンスを保持しているかどうかをinstanceof演算子で確認してコンパイルエラーを回避します。

public class Main {
    public static void main(String[] args) {
        Fuzi f1 = new Fuzi();
        MyClass mc = f1;
        // ここからコンパイルエラーを回避する
        if (mc instanceof Sakura) {
            Sakura s = (Sakura) mc;
        } else {
            // mcがSakura型でない場合は、何もしない
        }
        System.out.println(mc instanceof MyClass); // 出力結果 -> true
        System.out.println(mc instanceof Fuzi); // 出力結果 -> true
        System.out.println(mc instanceof Sakura); // 出力結果 -> false
    }
}

class MyClass {}
class Fuzi extends MyClass {}
class Sakura extends MyClass {}

コード例の解説

今回は、下記の部分だけ切り抜いて解説します。

if (mc instanceof Sakura) {
    Sakura s = (Sakura) mc;
} else {
    
}
  1. if文の条件式を変数mcがSakuraクラスのインスタンスを持つかどうかと定義して、
  2. trueなら、ダウンキャストを行い、
  3. falseなら、何もしないという処理を行います。

今回は、if文の条件式がfalseとなり何もしないという処理が行われ、ダウンキャストによるコンパイルエラーが回避され、次の処理であるSystem.out.println()の処理に移行できます。

Discussion