Java | 演算時の自動型変換(暗黙の型変換/型昇格)

Java Java
スポンサーリンク

では「演算時の自動型変換(暗黙の型変換/型昇格)」をプログラミング初心者向けに、やさしく・丁寧に・例題つきで解説します。実際のコード例と「よくあるエラー」の直し方、最後に練習問題(解答付き)も付けます。

概要(端的に)

Javaでは「違う型同士で演算するとき」、もっと情報量の多い(精度の高い)方の型に自動で変換してから計算するルールがあります。これを理解しておかないと「思った値にならない」「コンパイルエラーになる」ことがよくあります。

型変換の優先順位(覚え方)

演算で自動的に選ばれる型は次の順番(上が優先)で決まります:

double > float > long > int

つまり、double が混ざっていたら全て double に、float が混ざっていて double が無ければ全て float に、という感じです。

補足:byteshort は演算の直前に まず 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
  • 結果の型は doubleint に入れようとするとエラーまたはキャストが必要。

例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
Java
  • float + double の結果は doublefloat に戻すならキャストが必要。

例5:整数同士の割り算に注意!

int a = 5;
int b = 2;
double d = a / b; // 結果は 2.0 ではなく 2.0 に変換された 2 (=2.0)
Java
  • a / 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
  • -ssint に昇格してから符号反転されるため結果は int。そのまま short に代入できない(キャストが必要)。

どう直すか(実務的な対策)

  1. 結果の型は演算で決まることを理解する(double優先など)。
  2. 小さい型(byte/short)は演算結果を int に受けるのが安全。
  3. 小数点が必要なら、片方を明示的に double/float にする(例:5.03f)。
  4. どうしても小さい型に入れたい時は 明示的にキャストする(ただしデータの切捨て/オーバーフローに注意)。

よくあるエラー例と直し方

  • エラー: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
  • 精度の不足:floatdouble に混ぜると 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;
Java

r の値は?
解答:6.5(xdouble に昇格してから計算)


問題2

short a = 7, b = 3;
short c = a + b; // コンパイルされる?
Java

コンパイルされるか?されない場合の直し方は?
解答:コンパイルエラーになる。理由:a+bint。直し方: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。ilong に昇格して計算され、結果は long


問題5

float f = 1.2f;
double d = f + 2.3;
Java

d の型と値は?
解答ddouble、値は 3.5(fdouble に昇格)


問題6

short s = 10;
short t = -s;
Java

コンパイルされる?されない場合の直し方は?
解答:コンパイルエラーになることがある。理由:-sint。直し方:short t = (short)(-s); または int t = -s;


問題7

int a = 1;
double b = 2;
float c = a + (float)b;
Java

コンパイルされる?値は?
解答a + (float)bfloat なので float c に代入可能。結果は 3.0f


問題8(応用)

byte x = 10;
byte y = 20;
byte z = (byte)(x + y);
System.out.println(z);
Java

出力される値は?注意点は?
解答:30 と表示される。注意点:x + yint → キャストで byte に戻している。もし合計が 127 を超えるとオーバーフローして負の数になるので注意。


まとめ(超ざっくり)

  • 演算で「どの型で計算されるか」は自動で決まる(double > float > long > int の順)。
  • byte/short 同士でも演算は int に昇格されるので、代入先に注意。
  • 小数を得たいときはリテラルに .0 をつけるか片方をキャスト。
  • 必要な場合だけ明示的キャストを使う(データの切捨てやオーバーフローに注意)。
Java
スポンサーリンク
シェアする
@lifehackerをフォローする
スポンサーリンク
タイトルとURLをコピーしました