MeWrite Docs

ClassCastException

互換性のない型へのキャスト時に発生するJavaの実行時例外

概要

ClassCastExceptionは、オブジェクトを互換性のない型にキャストしようとした場合に発生するJavaの実行時例外です。コンパイル時には検出されず、実行時に発生するため注意が必要です。

エラーメッセージ

Exception in thread "main" java.lang.ClassCastException: class java.lang.String cannot be cast to class java.lang.Integer
    at com.example.MyClass.main(MyClass.java:8)

原因

  1. 不正なダウンキャスト: 親クラスの参照を、実際のオブジェクト型と異なるサブクラスにキャストしている
  2. ジェネリクスの型消去: raw型を使用した際に、実行時に型の不一致が発生する
  3. ClassLoaderの違い: 異なるClassLoaderでロードされた同名のクラス間でキャストを試みている
  4. コレクションの型不一致: raw型のコレクションに異なる型のオブジェクトが混在している

解決策

1. instanceofで型チェックを行う

キャスト前にinstanceofで型を確認する。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
Object obj = getSomeObject();

// NG: 直接キャスト
String str = (String) obj; // ClassCastExceptionの可能性

// OK: instanceofで確認
if (obj instanceof String) {
    String str = (String) obj;
    System.out.println(str);
} else {
    System.out.println("Stringではありません: " + obj.getClass().getName());
}

2. Java 16以降のパターンマッチングを使う

instanceofとキャストを一度に行える。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
Object obj = getSomeObject();

// パターンマッチング(Java 16+)
if (obj instanceof String str) {
    System.out.println(str.toUpperCase());
} else if (obj instanceof Integer num) {
    System.out.println(num * 2);
}

// switch式でのパターンマッチング(Java 21+)
switch (obj) {
    case String s  -> System.out.println("文字列: " + s);
    case Integer i -> System.out.println("整数: " + i);
    case null      -> System.out.println("null");
    default        -> System.out.println("その他: " + obj.getClass());
}

3. ジェネリクスを正しく使用する

raw型を避け、型パラメータを明示する。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
// NG: raw型(コンパイル警告は出るが実行時にClassCastException)
List list = new ArrayList();
list.add("hello");
list.add(123);
String s = (String) list.get(1); // ClassCastException

// OK: ジェネリクスでコンパイル時に型安全性を確保
List<String> typedList = new ArrayList<>();
typedList.add("hello");
// typedList.add(123); // コンパイルエラー(実行前に検出)

4. ClassLoader問題の診断

異なるClassLoaderで同一クラスをロードした場合の対処。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
Object obj = loadFromExternalClassLoader();

// クラス名は同じでもClassLoaderが異なると別クラス扱い
System.out.println("オブジェクトのクラス: " + obj.getClass().getName());
System.out.println("ClassLoader: " + obj.getClass().getClassLoader());
System.out.println("期待するClassLoader: " + MyClass.class.getClassLoader());

// 同一ClassLoaderか確認
if (obj.getClass().getClassLoader() == MyClass.class.getClassLoader()) {
    MyClass casted = (MyClass) obj;
}

関連エラー

Java の他のエラー

最終更新: 2026-02-03