【Java】キャスト変換とは?仕組みと使い方を徹底解説!初心者向けサンプル付き

お疲れ様です。はるさらと申します。

Javaを勉強していると、
キャスト変換」という言葉を耳にするかもしれません。

これは、Javaでプログラミングをする上で、
データの種類(型)を一時的に変えるために、
とっても重要で基本的な仕組みなんです。

この記事では、経験の浅い方でもつまずかないように、
Javaのキャスト変換について、「なぜ必要なのか?」
「どうやって使うのか?」具体的なサンプルコードを交えて、
かみ砕いて解説していきます。


キャスト変換とは?

まず、キャスト変換とは何か?を一言でまとめます。

Javaにおけるキャスト変換とは、
「あるデータ型の値を、別のデータ型の値として一時的に扱う」ための処理のことです。

例えば、

  • 整数の「int型」の値を、より大きな整数の「long型」として扱いたい
  • 小数の「double型」の値を、整数の「int型」として扱いたい
  • 親クラス(スーパークラス)のオブジェクトを、子クラス(サブクラス)の型として扱いたい

といった、データ型が異なる場面で、
Javaに「この値をこの型として扱ってください!」と
明示的に指示するためのものです。

キャスト変換が必要な理由

「なんで、わざわざ型を変えないといけないの?」と思いますよね。

これはJavaが静的型付け言語という性質を持っているためです。

静的型付け言語であるJavaでは、
変数の型は宣言した後は変わりません。

型の違うデータをそのまま代入しようとすると、
プログラムがエラーになってしまいます。

型が違うとエラーになる例

int num = 10.5; // これはコンパイルエラー!double型の値をint型に入れられない

ここで「キャスト変換」が登場します。

Javaには、大きく分けて2種類のキャストがあります。

  1. 暗黙的な型変換(自動型変換)
  2. 明示的な型変換(キャスト)

この2つを理解すると、キャスト変換の使いどころが
思い浮かぶようになってきます。

暗黙的な型変換(アップキャスティング)とは?

暗黙的な型変換(またはアップキャスティング)は、
データが失われる心配がない場合に、
Javaが自動的に行ってくれる型変換です。

例えば、小さな箱(int)の中身を、
より大きな箱(longdouble)に移すようなイメージです。

変換元変換先安全性キャスト記法
intlong不要
intdouble不要
floatdouble不要

これは安全なので、特に何も書かなくてもJavaが自動で変換してくれます。

明示的な型変換(ダウンキャスティング)とは?

明示的な型変換、これが一般的に「キャスト」と呼ばれる処理で、
データ型の名前を**()で囲って**記述する必要があります。

これは、データが失われる可能性(精度が落ちる、値が入りきらないなど)がある場合に
必要になります。

例えば、大きな箱(double)の中身を、
小さな箱(int)に移すようなイメージです。

変換元変換先安全性キャスト記法
doubleint×(小数点が失われる)必要
longint×(値が大きすぎる可能性がある)必要
親クラス子クラス×(実行時エラーの可能性)必要

この「データが失われるかもしれないから、
あなたの責任でやってね!」
というのが明示的なキャストの本質です。


基本を学ぼう!プリミティブ型のキャスト

まずは、Javaの基本的なデータ型である
プリミティブ型intdoubleなど)のキャストから見ていきましょう。

サンプルコード1:プリミティブ型の基本キャスト

経験の浅い方が最初につまずきやすいのは、
「小数点の切り捨て」 の挙動です。

double型をint型にキャストすると、
小数の部分は切り捨てられてしまうことを確認してみましょう。

public class PrimitiveCastExample {
    public static void main(String[] args) {
        // 暗黙的な型変換(int -> double: 安全なのでキャスト不要)
        int integerValue = 10;
        double doubleValueAuto = integerValue; // 10.0 に自動変換される

        // 明示的な型変換(double -> int: データ欠損の可能性があるためキャストが必要)
        double decimalValue = 10.85;
        // (int) を使って明示的に int型 にキャストする
        int integerValueCasted = (int) decimalValue; 
        
        // long型からint型へのキャスト(値が収まる場合はOKだが、明示的なキャストは必須)
        long longValue = 200L;
        // (int) を使って明示的に int型 にキャストする
        int integerValueFromLong = (int) longValue;

        System.out.println("--- プリミティブ型のキャスト結果 ---");
        System.out.println("int -> double (自動): " + doubleValueAuto);
        System.out.println("double (10.85) -> int (明示): " + integerValueCasted);
        System.out.println("long (200L) -> int (明示): " + integerValueFromLong);
    }
}

【実行結果】

--- プリミティブ型のキャスト結果 ---
int -> double (自動): 10.0
double (10.85) -> int (明示): 10
long (200L) -> int (明示): 200

コードの重要なポイント

  • double doubleValueAuto = integerValue; のように、
    小さい型から大きい型への代入は、キャスト記法なしでOKです(自動変換)。
  • int integerValueCasted = (int) decimalValue; のように、
    大きい型から小さい型へ変換する場合、
    (変換したい型) という形で明示的にキャストする必要があります。
  • double から int へのキャストでは、
    値が 10.85 から 10 に切り捨てられていることに注目してください。
    これがデータ欠損の典型例です。
    丸めたい場合は、Math.round()などのメソッドを使うのが一般的です。

実務で役立つ!参照型のキャスト

プリミティブ型だけでなく、
Javaではクラスのオブジェクト(参照型)でもキャスト変換を行います。

これは主に**ポリモーフィズム(多態性)**と組み合わせて使用されます。

サンプルコード2:クラス間のアップキャスト・ダウンキャスト

ここでは、「動物」を親クラス、
「犬」を子クラスとして、キャストの挙動を見てみましょう。

// 親クラス
class Animal {
    public void cry() {
        System.out.println("動物が鳴きました");
    }
}

// 子クラス
class Dog extends Animal {
    @Override
    public void cry() {
        System.out.println("ワンワン!");
    }
    public void run() {
        System.out.println("犬が走ります");
    }
}

public class ReferenceCastExample {
    public static void main(String[] args) {
        // 1. アップキャスト (安全なのでキャスト不要)
        Dog dog = new Dog();
        Animal animal = dog; // DogオブジェクトをAnimal型として扱う (自動)
        
        System.out.println("--- 参照型のキャスト結果 ---");
        animal.cry(); // 実行されるのはDogクラスのメソッド(オーバーライドされているため)
        // animal.run(); // コンパイルエラー!Animal型にはrun()メソッドがない
        
        // 2. ダウンキャスト (明示的なキャストが必要)
        // Animal型として扱われていたオブジェクトを、再度 Dog型として扱う
        if (animal instanceof Dog) { // 安全のため、instanceofでチェック
            Dog realDog = (Dog) animal; // (Dog) を使って明示的にダウンキャスト
            realDog.run(); // Dog型に戻したので、run()メソッドが呼べる
        }
        
        // 3. 危険なダウンキャストの例 (実行時エラー: ClassCastException)
        // Animal animal2 = new Animal(); 
        // Dog dog2 = (Dog) animal2; // ★実行時エラーの可能性!
    }
}

【実行結果】

--- 参照型のキャスト結果 ---
ワンワン!
犬が走ります

コードの重要なポイント

  • Animal animal = dog;アップキャスト)は、自動的に行われます。
    これは、Dogは必ずAnimalでもある、という関係が成り立つためです。
    この場合、animal変数から呼べるメソッドは
    Animal型で定義されているものに限定されます。
  • Dog realDog = (Dog) animal;ダウンキャスト)は、
    明示的なキャストが必要です。
    これは、「本当にそのオブジェクトはDog型として扱えるのか?」という
    保証がないためです。
  • ダウンキャストを行う際は、if (animal instanceof Dog) のように、
    instanceof演算子を使って、
    本当にその型に変換可能かを実行前にチェックすることが、
    実務では必須となります。
    このチェックがないと、変換できない場合に
    **ClassCastException**という致命的な実行時エラーが発生してしまいます。

キャスト変換の「落とし穴」と代替手法

キャストは便利ですが、特に経験の浅い方が間違えやすいポイントや、
安全な代替手法があります。

経験の浅い方が間違えやすいポイント

1. プリミティブ型のキャストでは「四捨五入」されない

先ほどの例の通り、double から int へのキャストは常に切り捨てです。
四捨五入したい場合は、キャストの前にMath.round()メソッドを使って、
値を整数に丸めるようにしましょう。

double value = 10.85;
// NG: 10 になる
int ng = (int) value; 
// OK: 11 になる (long型をint型にキャスト)
int ok = (int) Math.round(value); 

2. 参照型のキャストは「型の互換性」が必須

全く関係のないクラス同士をキャストしようとしてもできません。
例えば、String型をInteger型にキャストすることはできません。

また、ダウンキャストは、もともと子クラスとして生成されたオブジェクト
親クラスの変数に入れている場合にのみ成功します。

サンプルコード3:Stringからintへの変換はキャストではない

プログラミングで頻繁に出てくるのが、
文字列(String)を数値(int)に変換する処理です。

これを「キャスト」だと誤解している方もいるかもしれません。

これは厳密には**キャスト変換ではなく、「解析(パース)」**と呼ばれる処理です。

Java

public class ConversionAlternativeExample {
    public static void main(String[] args) {
        String numberString = "12345";
        
        // NG: これはコンパイルエラー!Stringとintは互換性がないのでキャスト不可
        // int num = (int) numberString; 
        
        // OK: Integerクラスのparse...メソッドで文字列を解析する
        try {
            int parsedInt = Integer.parseInt(numberString);
            System.out.println("String -> int (解析): " + parsedInt);
            
            // 変換に失敗する例
            String invalidString = "123a";
            // ★実行時エラーの可能性!
            // int errorInt = Integer.parseInt(invalidString); 
            
        } catch (NumberFormatException e) {
            System.out.println("エラー: 数値に変換できない文字列です");
        }
    }
}

【実行結果】

String -> int (解析): 12345

コードの重要なポイント

  • Integer.parseInt(String) のように、
    parse系のメソッドは、文字列をその型の値に**変換(解析)**するものです。
    キャストとは目的が異なります。
  • この変換は、もし文字列が数値として正しくない場合(例:"123a")、NumberFormatExceptionという実行時エラーを発生させます。
    そのため、実務ではtry-catchブロックでエラー処理をすることが必須となります。

まとめ

最後に、この記事のポイントをおさらいしましょう!

  • キャスト変換とは、あるデータ型の値を、
    別のデータ型として一時的に扱うための処理です。
  • 自動型変換(暗黙的なキャスト):小さい型から大きい型へは、
    データ欠損がないので自動でOK。
  • 明示的なキャスト:大きい型から小さい型へ、または参照型のダウンキャストには、
    (変換したい型) という形式で明示的な指定が必要です。
  • 注意点:明示的なキャストでは、データの切り捨てや**ClassCastExceptionNumberFormatExceptionなどの
    実行時エラーが発生するリスクがあります。
    instanceoftry-catch**を使って安全性を確保しましょう!

キャスト変換は、Javaの学習を進める上で必ず必要なスキルです。
この記事のサンプルコードを繰り返し試して、
安全かつ正確に使いこなせるようになりましょう!

また、当ブログには数値や型変換に関連する記事もありますので、ぜひご覧ください!

【Java】0除算の挙動と対策を徹底解説|初心者向けサンプル付き

【Java】BigDecimalでの0除算を徹底解説|初心者向けサンプル付き

【Java】0xffをbyteに変換する方法まとめ|初心者向けサンプル付き解説

どなたかのお役に立てば幸いです。
それではまたー!