この内容は古いバージョンです。最新バージョンを表示するには、戻るボタンを押してください。
バージョン:5
ページ更新者:atom
更新日時:2026-06-11 07:12:00

タイトル: キャスト
SEOタイトル: 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(&quot;42&quot;);           // 42
int n2 = Integer.parseInt(&quot;0x1A&quot;, 16);    // 26
// Integer.parseInt(&quot;abc&quot;); → NumberFormatException

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

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

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

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

エラー原因対処
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) や明示キャストを使う。