[Java]クラスの自動型変換・ダウンキャスト・instanceof演算子

わかりやすいJava_オブジェクト指向編を読んで勉強中。。

変数に指定したクラスの型への自動型変換

以下のコードでコンパイルエラーとなるのはどこ?

package net.fernwelt;

public class Z extends X{

  public int field = 0;
  public void zMethod(){}
  public void xMethod(){
    System.out.println(this.field);
  }

  public static void main(String[] args) {

    Z z;
    z = new X();
    z = new Z();
    System.out.println(z.field);
    z.xMethod();
    z.zMethod();

    X x = new Z();
    System.out.println(x.field);
    x.xMethod();
    x.zMethod();
  }
}

class X {
  public void xMethod(){}
}
  • 3箇所でコンパイルエラーとなる
  • 変数に代入される際にスーパークラスの型に自動変換される
  • 自動変換されてもインスタンス自体には変化がない。よーするに参照の型の問題なのですね。参照するインスタンスのアドレスは分かるけど、参照できるクラス型が指定されている
  • その変数からサブクラス独自のメンバに直接アクセスすることはできない。変数に指定したクラス型のインスタンスが参照できる部分のみのアクセスに制限される。
  • サブクラスの型にはそのまま戻せない。ダウンキャストしないとコンパイルエラー。

ダウンキャスト

サブクラスの型を指定した変数の参照は、そのスーパークラス型の変数には自動変換されて代入されるけども、逆は自動的には行われないためダウンキャストをする必要がある。 ダウンキャストするインスタンスの型が、ダウンキャスト後のサブクラス(またはキャスト後のクラスと同じ)なら問題なくキャストが行われる。違う場合は実行時例外 ClassCastException が発生する。

以下のコードはどうなる?

public class DownCast {
  public static void main(String[] args) {

    Object a = new A();
    Object b = new B();
    Object c = new C();

    try {
      b = (B) a;
      b = (B) b;
      b = (B) c;
    } catch (Exception e) {
      e.printStackTrace();
    }

  }
}

class A extends B {}
class B extends C {}
class C {}

結果

java.lang.ClassCastException: jp.fernweh.C cannot be cast to jp.fernweh.B
  at jp.fernweh.DownCast.main(DownCast.java:12)

instanceof 演算子

変数(インスタンスの参照を持つ) instanceof クラス型(返り値はboolean)

という書き方で、変数の参照先インスタンスは、指定したクラス型か?あるいは指定したクラスを継承しているか(指定したクラス型は参照先インスタンスのスーパークラスか)? をチェックすることができる。IS-A関係ならtrueを返す。変数に指定したクラス型は無関係(変数に定義されているのは参照の型であってインスタンスの型ではない)。

以下のコードはどう出力される?

public class InstanceofTest {
  public static void main(String[] args) {
    Object a = new A();
    Object b = new B();
    Object c = new C();

    System.out.println(a instanceof B);
    System.out.println(b instanceof B);
    System.out.println(c instanceof B);
  }
}

class A extends B{}
class B extends C{}
class C{}

結果

true
true
false

図にしてみた クラス変換の図

参考リンク:Javaの道:クラス(14.参照型の型変換とキャスト)

Share
関連記事