Java道|型変換とキャストの使い方

型が変わると、値の見え方も変わる。
Javaの型変換とキャストを知ると、エラーの理由と計算結果の違いが見えてくる。

Javaでは、変数に値を入れるときや、計算結果を別の変数に代入するときに、型がとても大切になります。

たとえば、int 型は整数を扱う型です。
一方、double 型は小数を含む数値を扱える型です。

同じ 980 という数字でも、int 型として扱えば 980、double 型として扱えば 980.0 のように表されます。見た目は似ていますが、Javaの中では「どの型として扱うか」がしっかり区別されています。

この型の違いがあるため、ある型の値を別の型の変数に入れるときには、Javaが自動で変換してくれる場合と、自分で変換を明示しないといけない場合があります。この記事では、指定内容に沿って Sample8.java、Sample8(エラーあり).java、Sample8.java(変更後)のみを使い、型変換とキャストの使い方を鬼滅の刃風の世界観にたとえながら整理します。

鬼滅の刃風にたとえると、型は「技を入れる器」のようなものです。int 型は整数だけを入れる小さめの器、double 型は小数も入れられる大きめの器です。小さい器の中身を大きい器へ移すのは自然にできますが、大きい器の中身を小さい器へ移すと、入りきらない部分が出ることがあります。そこで必要になるのが、キャストです。

型変換とは

型変換とは、ある型の値を別の型の値として扱えるように変えることです。

たとえば、int 型の値を double 型の変数に代入すると、整数の 980 が double 型の 980.0 として扱われます。

int price = 980;
double dprice = price;

この場合、price は int 型ですが、dprice は double 型です。
Javaは int 型の 980 を double 型の 980.0 に自動で変換してくれます。

変換前変換後
intdouble980 → 980.0
intlong980 → 980
doubleint58.7 → 58。ただしキャストが必要

型変換では、変換できる方向が大切です。
小さな型から大きな型へは、自動で変換できることが多いです。
しかし、大きな型から小さな型へは、情報が失われる可能性があるため、そのままでは代入できないことがあります。

鬼滅の刃風にたとえると、小さな技の力を大きな器へ移すのは安全です。
しかし、大きな力を小さな器へ押し込むと、一部の力がこぼれてしまう可能性があります。

大きなサイズの型に代入する

まずは、Javaが自動で型変換してくれる例を見ていきます。

int 型の値を double 型の変数に代入する場合です。

ファイル名:Sample8.java

class Sample8
{
    public static void main(String[] args)
    {
        int price = 980;

        System.out.println("刀の価格は " + price + " 円です。");

        System.out.println("double型の変数に代入します。");
        double dprice = price;

        System.out.println("刀の価格は " + dprice + " 円です。");
    }
}

実行結果

刀の価格は 980 円です。
double型の変数に代入します。
刀の価格は 980.0 円です。

このプログラムでは、最初に int 型の price に 980 を入れています。

int price = 980;

そのあと、double 型の dprice に price を代入しています。

double dprice = price;

このとき、price は int 型ですが、dprice は double 型です。
Javaは、int 型の 980 を double 型の 980.0 に自動で変換して代入します。

処理
int price = 980;980int
double dprice = price;980.0double

ここでは、int から double への変換なので、Javaが自動で型変換してくれます。

なぜ int から double へは自動で変換できるのか

int 型は整数を扱う型です。
double 型は、小数を含む数値を扱える型です。

つまり、double 型のほうが、int 型よりも広い範囲の情報を扱えます。

扱える値のイメージ
int整数
double整数と小数

int 型の 980 は、double 型でも 980.0 として表現できます。
情報が失われにくいため、Javaは自動で変換してくれます。

鬼滅の刃風にたとえると、int 型は小さめの竹筒、double 型は大きな水瓶です。
竹筒に入っている水を大きな水瓶に移すのは問題ありません。水瓶のほうが容量に余裕があるからです。

図:int から double への自動型変換

↓クリックすると拡大表示されます。

この図が示していること

この図では、int 型の 980 が double 型の 980.0 に変換される流れを示しています。

左側の int 型は整数を扱う型です。
右側の double 型は、小数も扱える型です。

int 型の値を double 型へ移す場合、double 型のほうが広い範囲の値を扱えるため、Javaが自動で型変換してくれます。

ここから分かることは、小さな型から大きな型への代入では、情報が失われにくいため、自動変換される場合があるということです。

そのまま代入できる場合とできない場合

型変換では、どの方向へ変換するかが大切です。

代入そのままできるか理由
int → doubleできるdouble のほうが小数も扱える
int → longできるlong のほうが大きな整数を扱える
double → intそのままではできないint では小数部分を表せない

int から double へは、整数を小数型へ広げるような変換です。
そのため、Javaが自動で変換できます。

一方、double から int へは、小数を含む可能性がある値を整数型へ入れることになります。
この場合、小数部分が失われる可能性があります。

Javaは、情報が失われる可能性がある変換を勝手には行いません。
そのため、double 型の値を int 型へ入れるには、キャストが必要になります。

小さなサイズの型に代入する

次に、double 型の値を int 型の変数へ代入する場合を見てみます。

この場合は、そのままではコンパイルできません。

ファイル名:Sample8.java(エラーあり)

class Sample8
{
    public static void main(String[] args)
    {
        double weight = 58.7;

        System.out.println("荷物の重さは " + weight + " キログラムです。");

        System.out.println("int型の変数に代入します。");
        int iweight = weight;

        System.out.println("荷物の重さは " + iweight + " キログラムです。");
    }
}

このプログラムでは、double 型の weight に 58.7 を入れています。

double weight = 58.7;

そのあと、int 型の iweight に weight を代入しようとしています。

int iweight = weight;

しかし、これはそのままではエラーになります。

理由は、double 型の 58.7 には小数部分があるからです。
int 型は整数しか扱えません。
そのため、58.7 を int 型に入れると、小数部分の .7 を表せません。

Javaは「小数部分が失われるかもしれない危ない変換だ」と判断するため、自動では変換しません。

なぜ double から int へはそのまま代入できないのか

double 型は、小数を含む値を扱えます。
int 型は、整数だけを扱います。

値の例小数を扱えるか
int58扱えない
double58.7扱える

double 型の値を int 型へ入れようとすると、小数部分が入らない可能性があります。

たとえば、58.7 を int 型にすると、58 になります。
このとき、.7 の部分は失われます。

これは、Javaにとって安全とは言えない変換です。
そのため、プログラマが「小数部分が失われる可能性を理解したうえで変換します」と明示する必要があります。

鬼滅の刃風にたとえると、double 型は大きな水瓶、int 型は小さな竹筒です。
大きな水瓶の水を小さな竹筒へ移すと、入りきらない水がこぼれるかもしれません。
だからJavaは、勝手には移し替えず、あなたの明確な指示を待ちます。

キャスト演算子とは

キャスト演算子は、Javaに対して「この型に変換して使います」と明示するための書き方です。

書き方は次の形です。

(型名)式

↓クリックすると拡大表示されます。

たとえば、double 型の weight を int 型に変換したい場合は、次のように書きます。

(int)weight

これは、weight の値を int 型として扱うという意味です。

書き方意味
(int)weightweight を int 型に変換する
(double)priceprice を double 型に変換する
(long)countcount を long 型に変換する

キャストは、Javaに対して「この変換を自分の判断で行います」と伝える書き方です。

キャストを使って小さな型へ代入する

double 型の値を int 型へ代入したい場合は、キャストを使います。

ファイル名:Sample8.java(変更後)

class Sample8
{
    public static void main(String[] args)
    {
        double weight = 58.7;

        System.out.println("荷物の重さは " + weight + " キログラムです。");

        System.out.println("int型の変数に代入します。");
        int iweight = (int)weight;

        System.out.println("荷物の重さは " + iweight + " キログラムです。");
    }
}

実行結果

荷物の重さは 58.7 キログラムです。
int型の変数に代入します。
荷物の重さは 58 キログラムです。

ここで大切なのは、58.7 が 58 になっていることです。

int iweight = (int)weight;

この処理では、double 型の weight を int 型にキャストしています。
その結果、小数点以下が切り捨てられます。

元の値int にキャストした結果
58.758
12.912
3.13
60.560

ここで注意したいのは、四捨五入ではないことです。
58.7 は 59 になるのではなく、58 になります。
12.9 も 13 ではなく、12 になります。

Javaの double から int へのキャストでは、小数点以下が切り捨てられます。

図:double から int へのキャスト

↓クリックすると拡大表示されます。

この図が示していること

この図では、double 型の 58.7 が、キャストによって int 型の 58 に変換される流れを示しています。

左側の double 型では、58.7 のような小数を含む値を扱えます。
右側の int 型では、整数だけを扱います。

そのため、double から int へ変換すると、小数点以下の .7 は失われます。
この変換は情報が失われる可能性があるため、Javaは自動では行いません。

ここから分かることは、小さな型へ変換するときには、キャストで明示的に指示する必要があるということです。

キャストすると何が起こるのか

キャストは便利ですが、注意も必要です。

特に、double 型から int 型へキャストすると、小数点以下が切り捨てられます。

double weight = 58.7;
int iweight = (int)weight;

この場合、iweight には 58 が入ります。

処理
double weight = 58.7;58.7
int iweight = (int)weight;58

この変換では、58.7 が 58 になります。
58.7 を四捨五入して 59 にしているわけではありません。

四捨五入ではなく切り捨て

ここはとても大切です。

元の値int キャスト後四捨五入では?
58.75859
12.91213
3.133
60.56061

キャストによる int 変換は、小数点以下を切り捨てます。
そのため、小数部分が重要な値では注意が必要です。

鬼滅の刃風にたとえると、double 型の 58.7 は「58.7段階の全集中度」です。
しかし int 型の器には小数の .7 が入らないため、58段階として扱われます。
少しの集中度が失われるイメージです。

大きな型への代入でもキャストは書ける

int 型から double 型への変換は、自動で行われます。

int price = 980;
double dprice = price;

このような場合でも、キャストを書くことはできます。

int price = 980;
double dprice = (double)price;

どちらも結果は同じです。

書き方結果
double dprice = price;980.0
double dprice = (double)price;980.0

ただし、int から double へのように安全に変換できる場合は、Javaが自動で型変換してくれます。
そのため、最初の学習段階では、無理にキャストを書かなくても大丈夫です。

自動の型変換と明示的な型変換の違い

型変換には、大きく分けて2つあります。

種類説明
自動の型変換Javaが自動で型を変えるint → double
明示的な型変換キャストを書いて自分で型を変えるdouble → int

Javaは、安全に変換できる場合だけ自動で型を変えます。

たとえば、int から double は安全に変換しやすいです。

int price = 980;
double dprice = price;

一方、double から int は情報が失われる可能性があります。

double weight = 58.7;
int iweight = (int)weight;

この場合は、キャストが必要です。

変換Javaの判断理由
int → double自動で変換する小数型のほうが広く扱える
double → int自動では変換しない小数部分が失われる可能性がある

Javaは型を厳しく管理する言語です。
だからこそ、危ない変換はプログラマに明示させるようになっています。

Sample8.javaの流れを整理する

今回扱う Sample8.java 系の流れを整理すると、次のようになります。

ファイル名内容ポイント
Sample8.javaint 型を double 型へ代入する自動で型変換される
Sample8.java(エラーあり)double 型を int 型へそのまま代入する小数部分が失われる可能性があるためエラー
Sample8.java(変更後)double 型を int 型へキャストして代入する小数点以下が切り捨てられる

最初の Sample8.java では、int 型の 980 を double 型へ代入しています。
これは、小さな型から大きな型への変換なので、自動で行われます。

Sample8.java (エラーあり)では、double 型の 58.7 を int 型へそのまま代入しようとしています。
これは、小数部分が失われる可能性があるため、そのままではエラーになります。

Sample8.java(変更後)では、(int)weight と書いて、明示的に int 型へ変換しています。
その結果、58.7 は 58 になります。

型変換を理解すると演算も分かりやすくなる

型変換とキャストは、代入だけでなく、演算の理解にもつながります。

たとえば、整数どうしの割り算と、小数を含む割り算では、結果の見え方が変わることがあります。

式のイメージ型の考え方
整数どうしの計算整数として扱われやすい
小数を含む計算小数として扱われやすい
int から double へ代入自動で 980 → 980.0 のように変換
double から int へ代入キャストが必要で、小数点以下が切り捨てられる

Javaでは、数値そのものだけでなく、その数値がどの型として扱われているかが重要です。

同じ 58 でも、int 型の 58 と double 型の 58.0 は、Javaの中では型が違います。
この違いを意識できるようになると、なぜこの結果になるのか、なぜこの代入はエラーになるのかが見えやすくなります。

キャストを使うときの注意点

キャストは、型を変換したいときに便利です。
ただし、特に大きな型から小さな型へ変換するときには注意が必要です。

注意点内容
情報が失われることがあるdouble から int では小数点以下が消える
四捨五入ではない58.7 は 59 ではなく 58
自分で明示する必要がある(int)weight のように書く
必要な場面でだけ使う自動変換できる場面では無理に書かなくてもよい

たとえば、体重、距離、金額の小数部分など、細かい値が大切な場面では、int にキャストすると必要な情報が失われるかもしれません。

double distance = 12.9;
int idistance = (int)distance;

この場合、idistance は 12 になります。
12.9 の .9 は消えてしまいます。

そのため、キャストは「変換後に情報が失われても問題ないか」を考えて使うことが大切です。

型変換とキャストで覚えておきたいこと

ポイント内容
型変換ある型の値を別の型として扱うこと
自動型変換Javaが自動で変換してくれること
キャストプログラマが明示的に型を変換すること
int → double自動で変換できる
double → intそのままでは代入できない
(int)weightweight を int 型へ変換する
小数点以下int へキャストすると切り捨てられる

型変換とキャストは、最初は少し細かい話に感じるかもしれません。
しかし、Javaでは型がとても大切です。

変数に値を入れるとき、計算するとき、別の型へ代入するとき、Javaは常に型を意識しています。

鬼滅の刃風にたとえると、型は「技を入れる器」です。
大きな器へ移すときは安全に移せます。
小さな器へ移すときは、入りきらない部分が失われる可能性があります。

だからこそ、double から int のような変換では、キャストを使って明示的に指示します。

int iweight = (int)weight;

この1行は、Javaに対して「小数部分が失われる可能性を理解したうえで、int 型として扱います」と伝える書き方です。

型を意識できるようになると、Javaの代入や計算結果がずっと読みやすくなります。