Java | 基礎文法:型変換(キャスト)

Java Java
スポンサーリンク

型変換(キャスト)の全体像

キャストは「コンパイラが自動で変換しない型へ、開発者の意図で変換を命じる」操作です。プリミティブ間の縮小変換(double → int など)や、参照型の上下変換(親子関係の型)で使います。キャストは「値が失われる」「失敗すると例外」が起こりうるため、どんな変換か、何が起きるか、どこで安全確認するかを理解するのが重要です。


プリミティブのキャスト(縮小変換の基本)

小数から整数へのキャストは「切り捨て」

double d = 3.9;
int n = (int) d;    // 3(小数点以下は切り捨て)
long m = (long) -3.9; // -3(負でも0方向へ切り捨て)
Java

キャストは丸めではなく「0方向への切り捨て」です。表示目的の丸めなら Math.round, Math.floor, Math.ceil を使い分けます。

範囲外へのキャストはオーバーフローする

int x = 130;
byte b = (byte) x; // -126(byteの範囲 -128..127 にラップしてしまう)
Java

縮小変換では「値を保てない」ことがあります。境界を超える可能性があるなら、事前に範囲チェックしてからキャストします。

int v = 200;
if (v < Byte.MIN_VALUE || v > Byte.MAX_VALUE) throw new IllegalArgumentException();
byte ok = (byte) v;
Java

演算で昇格した結果へのキャスト

byte a = 10, b = 20;
// a + b は int に昇格
byte s = (byte) (a + b); // 代入時だけ必要なキャストをまとめて書く
Java

(式) 全体を括弧でまとめてからキャストするのが安全です。部分的なキャストは意図せぬ結果を招くことがあります。


参照型(オブジェクト)のキャスト(上向き・下向き)

アップキャスト(上位型へ)は安全で暗黙可

class Animal {}
class Cat extends Animal {}
Cat c = new Cat();
Animal a = c; // アップキャスト(暗黙、自動)
Java

子から親へは常に安全です。API受け渡しで「広い型」を使いたいときに自然に行われます。

ダウンキャスト(下位型へ)は明示必須で要確認

Animal a = new Cat();
Cat c = (Cat) a; // ダウンキャスト(明示)
Java

参照の実体が Cat でないと ClassCastException になります。安全に行うには「型チェック」を合わせます。

Animal a = getAnimal();
if (a instanceof Cat) {
    Cat c = (Cat) a; // 安全
}
Java

Java 16+ ならパターンマッチで簡潔に書けます。

if (a instanceof Cat c) {
    // c を Cat として使える
}
Java

キャストは「実体に依存」する

Animal a = new Animal();
Cat c = (Cat) a; // 実体がCatでないため ClassCastException
Java

変数の型ではなく「中身の実体」が重要です。設計として「下位型を前提にしない」インターフェース化やメソッド提供を考えましょう。


キャストと丸め・文字コード(数値の意味を守る)

丸めたいなら Math を使う

double d = 3.5;
int r = (int) d;          // 3(切り捨て)
int round = (int) Math.round(d); // 4(四捨五入)
int floor = (int) Math.floor(d); // 3(下方向)
int ceil  = (int) Math.ceil(d);  // 4(上方向)
Java

「値の意味」を守るには丸めルールを明示します。表示だけなら printf("%.2f") が最短です。金額の厳密丸めは BigDecimal を選択します。

char とコードポイント

char c = 'A';
int code = (int) c; // 65
char j = (char) 0x3042; // 'あ'
Java

char は UTF-16 のコード単位です。BMP外(U+10000以上)は2単位(サロゲートペア)になるため、文字数操作では codePoints() を使うほうが安全です。


文字列と数値の変換は「キャストではない」

パースと文字列化を使う

String s = "123";
// int x = (int) s;   // NG:キャストではできない
int x = Integer.parseInt(s);    // OK:パース
String t = String.valueOf(456); // OK:文字列化
Java

「参照型同士のキャスト」で値の変換はできません。文字列⇔数値は「APIで変換」です。


ラッパー型とキャストの違い(オートボクシングに注意)

ラッパー間のキャストはできない

Number n = Integer.valueOf(10);
// Long l = (Long) n; // NG:実体がIntegerなので失敗
Java

「数値の型を取り替える」には、いったんプリミティブへ取り出してから作り直します。

Number n = Integer.valueOf(10);
long l = n.longValue();      // プリミティブへ
Long L = Long.valueOf(l);    // 別ラッパー型を作る
Java

null のアンボクシングは例外になるため防御します。

Integer ix = null;
// int v = ix; // NullPointerException
int v = (ix != null) ? ix : 0;
Java

よくある落とし穴と安全策(重要ポイントの深掘り)

整数除算で先にゼロが確定する

int a = 1, b = 2;
double bad = (double) (a / b); // 0.0(先に0が確定)
double good = (double) a / b;  // 0.5(先に浮動小数へ)
Java

キャストの位置で結果が変わります。「計算前に広げる」を意識してください。

キャスト前に範囲・意味を検証する

縮小変換は事前チェックで守ります。

long id = 3_000_000_000L;
if (id > Integer.MAX_VALUE) throw new IllegalArgumentException("範囲外");
int safeId = (int) id;
Java

参照型のダウンキャストは「必要最小限」に

設計で下位型を前提にしないよう、共通のインターフェースや抽象メソッドで操作を提供します。どうしても必要なら instanceof で守り、失敗時の代替経路(例外・スキップ)を決めておきます。


例題で身につける

例 1: 入力値を安全に整数化(丸め規則を明示)

public class ParseAndRound {
    public static void main(String[] args) {
        double tax = 12.345;
        int floor = (int) Math.floor(tax);        // 12
        int ceil  = (int) Math.ceil(tax);         // 13
        int round = (int) Math.round(tax);        // 12(.5未満は切り捨て、.5以上は切り上げ)
        System.out.println(floor + "," + ceil + "," + round);
    }
}
Java

例 2: 子型だけが持つメソッドを安全に使う(ダウンキャスト)

class Animal { void speak() { System.out.println("..."); } }
class Cat extends Animal { void meow() { System.out.println("meow"); } }

public class CastDemo {
    static void callIfCat(Animal a) {
        if (a instanceof Cat c) { // パターンマッチ(Java 16+)
            c.meow();             // 安全に子型メソッドへアクセス
        } else {
            a.speak();
        }
    }
    public static void main(String[] args) {
        callIfCat(new Cat());     // meow
        callIfCat(new Animal());  // ...
    }
}
Java

例 3: オーバーフローを避けるために「先に広げる」

public class OverflowSafe {
    public static void main(String[] args) {
        int big = 1_000_000;
        long safe = (long) big * big; // 片方を先に long へ
        System.out.println(safe);     // 1000000000000
    }
}
Java

仕上げのアドバイス(重要部分のまとめ)

キャストは「意図」と「失うもの」を明確にして使います。プリミティブ縮小は切り捨てとオーバーフローに注意し、必要なら丸め関数や範囲チェックを併用する。参照型のダウンキャストは instanceof で安全確認し、設計としては下位型依存を減らす。文字列⇔数値はキャストではなく API で変換、ラッパー間の変換も一度プリミティブへ。演算前に広い型へ変換する位置を意識すれば、整数除算やオーバーフローの罠を確実に避けられます。

タイトルとURLをコピーしました