では「演算時の自動型変換(暗黙の型変換/型昇格)」をプログラミング初心者向けに、やさしく・丁寧に・例題つきで解説します。実際のコード例と「よくあるエラー」の直し方、最後に練習問題(解答付き)も付けます。
概要(端的に)
Javaでは「違う型同士で演算するとき」、もっと情報量の多い(精度の高い)方の型に自動で変換してから計算するルールがあります。これを理解しておかないと「思った値にならない」「コンパイルエラーになる」ことがよくあります。
型変換の優先順位(覚え方)
演算で自動的に選ばれる型は次の順番(上が優先)で決まります:
double > float > long > int
つまり、double が混ざっていたら全て double に、float が混ざっていて double が無ければ全て float に、という感じです。
補足:
byteやshortは演算の直前に まずintに変換されてから演算されます(これが初心者が混乱しやすい点)。
なぜこうするの?(図でイメージ)
- 小さな箱(
byte,short,int)と大きな箱(long,float,double)があると想像してください。 - 精度を保つために、より大きな箱に移してから計算するイメージです。小さい箱に無理やり戻すと誤差やオーバーフロー、コンパイルエラーが起きます。
具体例と解説
例1:int と double
double d = 3 + 0.5; // 3 は int、0.5 は double → 3 が double に変換 → 結果は 3.5 (double)
Java- 結果の型は
double。intに入れようとするとエラーまたはキャストが必要。
例2:short と short
short a = 10;
short b = 20;
short c = a + b; // コンパイルエラー!
Java- 理由:
a + bの計算は、内部でまずintに変換されてから計算され、結果もintになるため、shortへ直接代入できません。 - 正しい書き方(キャストで戻す):
short c = (short)(a + b);
Javaただし、安全を期すなら結果を int に受けるのが一般的です:
int c = a + b;
Java例3:long と int
long L = 100L;
int i = 7;
long r = L + i; // OK: i が long に昇格される → 結果は long
Java例4:float と double
float f = 2.5f;
double d = 1.0;
double r = f + d; // f が double に変換される → 結果は double
Javafloat + doubleの結果はdouble。floatに戻すならキャストが必要。
例5:整数同士の割り算に注意!
int a = 5;
int b = 2;
double d = a / b; // 結果は 2.0 ではなく 2.0 に変換された 2 (=2.0)
Javaa / bは両方ともintなので整数除算になり結果は2(小数点以下切り捨て)。その後doubleに変換され2.0になります。- 小数結果を得たいなら片方を
double/floatにする:
double d = (double)a / b; // 結果は 2.5
// または
double d = 5.0 / 2; // 2.5
Java例6:単項マイナス(-)に注意
short s = 10;
short t = -s; // コンパイルエラーになることがある
Java-sはsをintに昇格してから符号反転されるため結果はint。そのままshortに代入できない(キャストが必要)。
どう直すか(実務的な対策)
- 結果の型は演算で決まることを理解する(double優先など)。
- 小さい型(byte/short)は演算結果を
intに受けるのが安全。 - 小数点が必要なら、片方を明示的に
double/floatにする(例:5.0や3f)。 - どうしても小さい型に入れたい時は 明示的にキャストする(ただしデータの切捨て/オーバーフローに注意)。
よくあるエラー例と直し方
- エラー:
possible lossy conversion from int to short- 原因:
short result = a + b;(a,b が short)→ 解決:short result = (short)(a + b);またはint result = a + b;
- 原因:
- 想定外の値:
5 / 2 == 2- 原因:整数除算 → 解決:
5.0 / 2または(double)5 / 2
- 原因:整数除算 → 解決:
- 精度の不足:
floatをdoubleに混ぜるとdoubleに- 対策:必要なら
float f = 3.14f;のようにリテラルにfを付ける、戻すときはキャスト。
- 対策:必要なら
実行例(サンプルプログラム)
public class TypePromotionDemo {
public static void main(String[] args) {
short s1 = 10, s2 = 20;
int sum = s1 + s2; // OK (結果は int)
System.out.println("short+short => int: " + sum);
double d = 3 + 0.5; // 3 が double に昇格
System.out.println("int+double => double: " + d);
int a = 5, b = 2;
System.out.println("int / int => int: " + (a / b)); // 2
System.out.println("double division: " + ((double)a / b)); // 2.5
short s3 = (short)(s1 + s2); // キャストで戻す(注意)
System.out.println("キャストで short に戻すと: " + s3);
}
}
Java練習問題(初心者向け) — 解答付き
問題は短めにして、考え方を書きます。
問題1
int x = 4;
double y = 2.5;
double r = x + y;
Javar の値は?
解答:6.5(x が double に昇格してから計算)
問題2
short a = 7, b = 3;
short c = a + b; // コンパイルされる?
Javaコンパイルされるか?されない場合の直し方は?
解答:コンパイルエラーになる。理由:a+b は int。直し方:int c = a + b; または short c = (short)(a + b);
問題3
int a = 9, b = 4;
System.out.println(a / b);
Java出力は何?
解答:2(整数除算)。小数を出すには (double)a / b などにする。
問題4
long L = 10000000000L;
int i = 5;
long r = i * L;
JavaこれはOK?結果の型は?
解答:OK。i が long に昇格して計算され、結果は long。
問題5
float f = 1.2f;
double d = f + 2.3;
Javad の型と値は?
解答:d は double、値は 3.5(f が double に昇格)
問題6
short s = 10;
short t = -s;
Javaコンパイルされる?されない場合の直し方は?
解答:コンパイルエラーになることがある。理由:-s は int。直し方:short t = (short)(-s); または int t = -s;
問題7
int a = 1;
double b = 2;
float c = a + (float)b;
Javaコンパイルされる?値は?
解答:a + (float)b は float なので float c に代入可能。結果は 3.0f。
問題8(応用)
byte x = 10;
byte y = 20;
byte z = (byte)(x + y);
System.out.println(z);
Java出力される値は?注意点は?
解答:30 と表示される。注意点:x + y は int → キャストで byte に戻している。もし合計が 127 を超えるとオーバーフローして負の数になるので注意。
まとめ(超ざっくり)
- 演算で「どの型で計算されるか」は自動で決まる(
double > float > long > intの順)。 byte/short同士でも演算はintに昇格されるので、代入先に注意。- 小数を得たいときはリテラルに
.0をつけるか片方をキャスト。 - 必要な場合だけ明示的キャストを使う(データの切捨てやオーバーフローに注意)。
