7.

Java 型キャスト (cast) 完全ガイド

編集
この記事の要点
  • キャスト = 値や参照を別の型として扱う変換。暗黙キャスト (拡大変換)明示キャスト (縮小変換)
  • 暗黙: int → long → float → double。情報損失なし
  • 明示: (int) d 等。小数点切捨て / オーバーフローに注意
  • 参照型キャスト: (Dog) animal。実際の型でなければ ClassCastException
  • Java 16+ Pattern Matching: if (obj instanceof Dog d) でキャスト不要

キャストとは

キャスト (cast) は値や参照を別の型として扱う変換です。Java は静的型付け言語なので、型が合わないと代入できません。キャストで明示的に変換します。

プリミティブ型の暗黙キャスト (拡大変換)

情報を失わない方向の変換は自動で行われます

// 拡大変換: byte → short → int → long → float → double
byte b = 100;
int i = b;                    // 暗黙 OK
long l = i;                   // 暗黙 OK
float f = l;                  // 暗黙 OK
double d = f;                 // 暗黙 OK

// 変換チェーン
byte → short → int → long
                  ↘ float → double
char → int (16bit → 32bit)

// char → int は OK
char c = 'A';
int code = c;                 // 65

// boolean だけは他の型と変換不可(int 0/1 とも)
// boolean → int  ★ コンパイルエラー

プリミティブ型の明示キャスト (縮小変換)

情報を失う可能性のある方向は明示的に書く必要があります。

double d = 3.7;
int i = (int) d;              // ★ (int) で明示。小数切り捨てで 3

double d2 = -3.7;
int i2 = (int) d2;            // -3 ★ 0 方向に切り捨て(Math.floor は -4)

// オーバーフロー
int big = 130;
byte b = (byte) big;          // -126 ★ ラップアラウンド (byte 範囲 -128〜127)

// 負の値
int neg = -1;
char c = (char) neg;          // 0xFFFF (char は符号なし 16bit)

// 切り捨て vs 四捨五入
double v = 3.7;
int floor = (int) v;                  // 3
int round = (int) Math.round(v);      // 4
int ceil  = (int) Math.ceil(v);       // 4

整数除算と小数除算

int a = 10, b = 3;

// 整数同士の除算は切り捨て
System.out.println(a / b);            // 3

// 片方を double にキャストで小数除算
System.out.println((double) a / b);   // 3.3333...
System.out.println(a / (double) b);   // 3.3333...
System.out.println((double) (a / b)); // 3.0 ★ 計算後にキャスト → 切り捨て後

// よくあるバグ
double avg = sum / count;             // sum, count が int だと小数失う
double avg2 = (double) sum / count;   // ✅ こちらが正しい

参照型のキャスト

クラス階層上でアップキャスト(広い方向)は暗黙、ダウンキャスト(狭い方向)は明示。

class Animal { }
class Dog extends Animal { void bark() { } }
class Cat extends Animal { void meow() { } }

// アップキャスト(暗黙)
Animal a1 = new Dog();        // OK: Dog is-a Animal

// ダウンキャスト(明示)
Dog d = (Dog) a1;             // OK: 実体が Dog なので
d.bark();

// ❌ 実体と違う型へのキャスト
Animal a2 = new Cat();
Dog d2 = (Dog) a2;            // ★ ClassCastException at runtime

// 安全にダウンキャスト: instanceof チェック
if (a2 instanceof Dog) {
    Dog d3 = (Dog) a2;
    d3.bark();
}

// Java 16+ Pattern Matching(短く書ける)
if (a2 instanceof Dog d4) {   // ★ キャスト不要、変数 d4 が直接使える
    d4.bark();
}

Autoboxing / Unboxing

プリミティブとラッパークラス間の自動変換(Java 5+)。

// Autoboxing: int → Integer
Integer i = 100;              // 内部的に Integer.valueOf(100)
List<Integer> list = new ArrayList<>();
list.add(5);                  // 自動でボクシング

// Unboxing: Integer → int
int n = i;                    // 内部的に i.intValue()
int sum = 0;
for (Integer x : list) {
    sum += x;                 // Unboxing
}

// ★ NullPointerException の罠
Integer maybe = null;
int v = maybe;                // ★ NullPointerException

// ★ Integer キャッシュ (-128〜127)
Integer a = 127, b = 127;
System.out.println(a == b);   // true ★ キャッシュで同一参照

Integer c = 128, d = 128;
System.out.println(c == d);   // false ★ 別インスタンス
System.out.println(c.equals(d)); // true

文字列との変換

// String → int
int n = Integer.parseInt("42");           // 42
int n2 = Integer.parseInt("0x1A", 16);    // 26
// Integer.parseInt("abc"); → NumberFormatException

// int → String
String s1 = String.valueOf(42);           // "42"
String s2 = Integer.toString(42);         // "42"
String s3 = "" + 42;                      // "42" ★ 連結(やや非推奨)

// double → String / String → double
String ds = String.valueOf(3.14);
double dv = Double.parseDouble("3.14");

// Object → String
Object o = new Date();
String os = o.toString();                 // toString() を呼ぶ
String os2 = String.valueOf(o);           // null セーフ(null なら "null")

キャストでよくあるエラー

エラー原因対処
ClassCastException実際の型と違うクラスへキャストinstanceof で事前確認
NumberFormatException数値でない文字列を parseInttry-catch / 正規表現バリデーション
NullPointerExceptionnull を UnboxingNull チェック / Optional
意図しない切捨て整数除算で小数になるはずが int に事前に (double) キャスト
オーバーフロー大きな値を小さな型に受け側を long / Math.toIntExact

ジェネリクスとキャスト

// ジェネリクス: コンパイル時の型チェック
List<String> strs = new ArrayList<>();
strs.add("hello");
String s = strs.get(0);           // ★ キャスト不要

// raw type は警告
List raw = new ArrayList();
raw.add(42);
String x = (String) raw.get(0);   // ★ ClassCastException 実行時

// ワイルドカード
List<? extends Number> nums = new ArrayList<Integer>();
Number n = nums.get(0);            // Number として受ける(Integer かもしれない)

// 型消去 (Type Erasure) の影響
public <T> T cast(Object o) {
    return (T) o;                  // unchecked cast 警告
}

Pattern Matching for instanceof (Java 16+)

Object obj = "hello";

// Java 15 まで
if (obj instanceof String) {
    String s = (String) obj;
    System.out.println(s.toUpperCase());
}

// Java 16+
if (obj instanceof String s) {
    System.out.println(s.toUpperCase());
}

// 複雑な条件と組み合わせ
if (obj instanceof String s && s.length() > 5) {
    // ...
}

// switch でも (Java 21+)
String result = switch (obj) {
    case Integer i  -> "int " + i;
    case String s   -> "str " + s.length();
    case int[] arr  -> "arr len " + arr.length;
    case null       -> "null";
    default         -> "unknown";
};

FAQ

Q: (int)Math.round() の違いは?
A: (int) は 0 方向に切り捨て(-3.7 → -3)、Math.round() は四捨五入(-3.7 → -43.5 → 4)。

Q: (double) (a / b)(double) a / b の違いは?
A: 前者は int 除算後に double 変換(切捨てが先)、後者は double 除算(小数で計算)。優先順位の罠です。

Q: 配列のキャストは?
A: Object[] → String[] は実行時に ArrayStoreException の可能性。Arrays.copyOf(arr, len, String[].class) や明示キャストを使う。

編集
Post Share
子ページ

子ページはありません

同階層のページ
  1. 基本事項
  2. HTMLへの埋め込み
  3. 変数
  4. 可変変数
  5. 定数
  6. データ型
  7. キャスト
  8. エスケープ文字
  9. 配列
  10. 演算子
  11. 代入の際の注意点
  12. 条件分岐
  13. 繰り返し処理
  14. クラスとインスタンス
  15. コンストラクタ
  16. 関数
  17. スーパーグローバル変数
  18. スコープ
  19. staticについて
  20. yieldについて
  21. ファイルのアップロード方法
  22. DB接続方法
  23. SQL実行方法
  24. カプセル化の具体例
  25. 継承の構文
  26. オーバーライド
  27. ポリモーフィズム(多様性)の具体例
  28. 抽象クラス・メソッドの構文と具体例
  29. GET通信
  30. try catchで全てのエラーを拾う方法

最近更新/作成されたページ