🎯

【Java】クラス解説24・ダウンキャスト

2024/01/23に公開

コンパイルエラーを起こすコード例

public class Main {
    public static void main(String[] args) {
        Fuzi f1 = new Fuzi();

        // アップキャスト。
        // スーパークラス型の変数にサブクラスのインスタンスを代入する。問題なし。
        MyClass mc = f1;

        // コンパイルエラー
        // サブクラス型の変数にスーパークラス型の変数を直接代入することはできない。
        Fuzi f2 = mc; 
    }
}

class MyClass {}

class Fuzi extends MyClass {}

コード例の解説

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

public class Main {
    public static void main(String[] args) {
        Fuzi f1 = new Fuzi();
        MyClass mc = f1;
        Fuzi f2 = mc; 
    }
}

Mainクラスで、

  1. サブクラス型の変数f1にサブクラスのインスタンスを代入します。
  2. スーパークラス型の変数mcに、サブクラスのインスタンスが代入された変数f1を代入します。(アップキャスト)
  3. サブクラス型の変数f2に、サブクラスのインスタンスが代入されたスーパークラス型の変数mcを直接代入しようとしますが、コンパイルエラーとなります。
    サブクラス型の変数にサブクラスのインスタンスを代入しようとしているので、エラーが起きないように思いますが、スーパークラス型の変数mcにFuziクラスのインスタンスが代入されているかどうかはコンパイラが判断できません。これはJavaの性質上どうしようもありません。

ダウンキャストのコード例

上記のコンパイルエラーを回避するコード例を記述します。

public class Main {
    public static void main(String[] args) {
        Fuzi f1 = new Fuzi();
        MyClass mc = f1;
        // ダウンキャスト
        Fuzi f2 = (Fuzi) mc;
    }
}

class MyClass {}

class Fuzi extends MyClass {}

コード例の解説

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

public class Main {
    public static void main(String[] args) {
        Fuzi f1 = new Fuzi();
        MyClass mc = f1;
        // ダウンキャスト
        Fuzi f2 = (Fuzi) mc;
    }
}

Mainクラスで、

  1. サブクラス型の変数f1にサブクラスのインスタンスを代入します。
  2. スーパークラス型の変数mcに、サブクラスのインスタンスが代入された変数f1を代入します。(アップキャスト)
  3. サブクラス型の変数f2に、サブクラスのインスタンスが代入されダウンキャストした変数mcを代入します。今回はエラーが起こりません。
    先程、Javaの性質上、スーパークラス型の変数mcにFuziクラスのインスタンスが代入されているかどうかコンパイラが判断できませんと言いましたが、そのため、変数mcにFuziクラスのインスタンスが代入されていることを、(Fuzi)により明示的にダウンキャストすることにより、コンパイルが判断できるようにしているのです。

Discussion