キャストの罠
キャストの罠
このレッスンでできるようになること。ダウンキャストがコンパイルを通るのに実行時に落ちる場面を、あらかじめ見抜けるようになります。
親型から子型へ変換することをダウンキャストと呼びます。逆のアップキャストは安全なので何も書かずに通りますが、ダウンキャストは書き手が保証する形になります。
class Animal {}
class Dog extends Animal {}
class Cat extends Animal {}
Animal a = new Cat();
Dog d = (Dog) a;この2行はコンパイルを通ります。a の宣言型は Animal で、Dog は Animal の子なので、コンパイラは中身が Dog である可能性を否定できないからです。しかし実行すると ClassCastException が投げられます。中身は Cat であって Dog ではないからです。
コンパイルエラーになるのはどんなときか
継承の線でまったくつながっていない型どうしのキャストは、コンパイルの時点で弾かれます。Dog と Cat は兄弟なので、Dog d = (Dog) new Cat(); と直接書けばコンパイルエラーです。いったん Animal 型の変数に入れると、コンパイラの目には可能性が残るので通ってしまい、実行時まで問題が先送りされます。この差が試験でよく問われます。
落ちる前に確かめる
安全に書きたいときは instanceof で中身を確かめてからキャストします。a instanceof Dog が true のときだけキャストすれば、例外は起きません。なお null に対するキャストはいつでも成功し、例外にはなりません。null を instanceof で調べると必ず false になる点と合わせて覚えておくと迷いません。
演習では、例外の名前を実際に取り出して確かめます。例外のクラス名は e.getClass().getSimpleName() で取れます。
要件
- 変数の宣言型は
Animalにする tryとcatchで例外を受け止める- 例外時は
e.getClass().getSimpleName()を返す
入出力例
tryCast(1) → "Dog"
tryCast(2) → "ClassCastException"ヒント
編集 LuaGate編集部