Javaでキャストを使ったとき、
ClassCastExceptionが発生して困ったことはありませんか?🤔
この記事では、
- なぜエラーが起きるのか
- 安全にキャストする方法(instanceof / パターンマッチング)
を初心者向けにわかりやすく解説します。
❗ なぜエラーが起きるのか?
次のコードは一見問題なさそうですが、実行時にエラーになります。
Animal animal = new Dog();
Puppy puppy = (Puppy) animal; // ClassCastException
なぜでしょうか?
👉 実体はDogなのに、Puppyとして扱おうとしているからです。
🐶 クラス関係(図解)
Animal
└ Dog(実体)
└ Puppy(ここにいない)
👉 この状態で「Puppyとして扱う」ことはできません。
🔗 instanceofで安全にチェック
キャストする前に、型を確認することでエラーを防げます。
if (animal instanceof Puppy) {
Puppy puppy = (Puppy) animal;
}
👉 instanceof は
「その型として扱えるか?」をチェックする仕組みです。
✅ パターンマッチング(Java16以降)
Java16以降では、もっとシンプルに書けます。
if (animal instanceof Puppy p) {
p.play();
}
これは以下をまとめて行っています👇
- 型チェック
- キャスト
- 変数宣言
👉 安全かつシンプルに書けるのがポイントです
💻 サンプルコード(比較)
class Animal {}
class Dog extends Animal {
void bark() {
System.out.println("Woof!");
}
}
class Puppy extends Dog {
void play() {
System.out.println("Playing!");
}
}
public class Main {
public static void main(String[] args) {
Animal obj = new Dog();
test(obj);
testSmart(obj);
}
// 従来の書き方
static void test(Object obj) {
if (obj instanceof Puppy) {
Puppy p = (Puppy) obj;
p.play();
} else if (obj instanceof Dog) {
Dog d = (Dog) obj;
d.bark();
}
}
// パターンマッチング
static void testSmart(Object obj) {
if (obj instanceof Puppy p) {
p.play();
} else if (obj instanceof Dog d) {
d.bark();
}
}
}
🆚 比較(旧 vs 新)
| 項目 | 従来の書き方 | パターンマッチング |
|---|---|---|
| 書き方 | 冗長 | シンプル |
| キャスト | 必須 | 不要 |
| 可読性 | △ | ◎ |
| ミス防止 | △ | ◎ |
👉 パターンマッチングの方が安全で読みやすいです
🛠 ポリモーフィズムという考え方
ここまでのコードは「型によって処理を分ける」書き方です。
if (obj instanceof Dog) { ... }
しかし実務では、
振る舞いをオブジェクトに任せる(ポリモーフィズム)の方がシンプルだと聞きます。
abstract class Animal {
abstract void action();
}
class Dog extends Animal {
void action() {
System.out.println("Woof!");
}
}
class Puppy extends Dog {
void action() {
System.out.println("Playing!");
}
}
Animal animal = new Dog();
animal.action();
👉 instanceof を使わなくても処理できます
✔ まとめ
- キャストは安全ではない(実体の確認が必要)
- instanceof で型チェックができる
- Java16以降はパターンマッチングが便利
- 実務ではポリモーフィズムも重要
💡 最後に
キャストは
👉 「変身」ではなく「見方を変えるだけ」
だからこそ、
実体(インスタンス)を意識することが大切です。
同じように悩んだ方の参考になれば幸いです 🙌