こんにちは、プログラミング解説ブログへようこそ。
今回は Java初心者がよくハマる「double型をint型に代入するとコンパイルエラーになる問題」 を徹底解説します。
1. まず結論:暗黙ではできません
double d = 3.5;
int x = d; // コンパイルエラー!
なぜエラーになるのか?
Javaでは 「情報が失われる可能性がある縮小変換(narrowing conversion)」 は暗黙に行われません。
つまり、double の小数部分や桁数を int に代入すると、データの一部が消えるかもしれないため、コンパイラが安全のため拒否しているのです。
2. 自動型変換(widening)との違い
Javaでは型変換のルールとして、次のように決まっています。
元の型 代入先 暗黙でOK?
int double ✅ 自動変換OK(widening)
double int ❌ 自動変換NG(narrowing)
char int ✅ 自動変換OK(Unicode値に変換)
int → double のように 大きな型に拡張する場合 は自動で代入可能です。
逆に double → int のように 小さな型に縮める場合 はキャストが必要になります。
3. キャストで解決
double d = 3.9;
int x = (int) d; // 小数部分は切り捨て
System.out.println(x); // 3
int y = (int) -3.9;
System.out.println(y); // -3
ポイント:小数部分は「0方向に丸め」られます(切り捨て)。
4. 特殊値(NaNやInfinity)の扱い
double d = Double.NaN; int x = (int)d; → x == 0
値が int の範囲を超えている場合 → Integer.MAX_VALUE / Integer.MIN_VALUE に丸められる
つまり、例外は投げられず、極端な値は「安全な最大/最小値」に変換されます。
5. なぜ安全装置になっているのか
暗黙で代入すると、
小数部分が知らぬ間に切り捨てられたり
値が範囲外で壊れたり
というバグの温床になってしまいます。
Javaは「ここで情報が失われるぞ」とプログラマに自覚させるために、明示的なキャスト を要求しているわけです。
6. 安全な代入のコツ
四捨五入したい場合:
int x = (int)Math.round(d); // 3.5 -> 4
範囲をチェックして代入する場合:
if (d > Integer.MAX_VALUE) {
x = Integer.MAX_VALUE;
} else if (d < Integer.MIN_VALUE) {
x = Integer.MIN_VALUE;
} else {
x = (int)d;
}
NaN や Infinity は事前に判定して処理することもできます:
if (Double.isNaN(d) || Double.isInfinite(d)) {
x = 0; // 適切に処理
}
まとめ
double → int は 縮小変換のため暗黙ではNG
キャスト (int) を付ければ小数部は切り捨てられて代入可能
Java は「情報が失われる可能性」を警告するため、コンパイルエラーを出す
初心者がハマりやすい罠なので、ぜひ覚えておきましょう!