Java | 基礎文法:型変換(自動)

Java Java
スポンサーリンク

型変換(自動)の全体像

Java の「自動型変換」は、コンパイラが安全だと判断できる範囲で型を広げたり(拡大変換)、式の計算前に統一の型へ昇格させたりする仕組みです。代表は「拡大プリミティブ変換(widening)」「数値昇格(numeric promotion)」「文字列連結時の自動文字列化」「オートボクシング/アンボクシング」です。逆に「縮小変換(narrowing)」は自動では行われず、明示的なキャストが必要になります。


拡大プリミティブ変換(widening)

安全に広がる方向

int i = 100;
long l = i;      // OK: int → long(情報は失われない)
float f = l;     // OK: long → float(厳密値ではなくなる可能性はあるが許容される)
double d = f;    // OK: float → double
char c = 65;
int x = c;       // OK: char → int('A' のコードポイント 65)
Java

プリミティブでは小さい器から大きい器へは自動変換されます(byte → short → int → long → float → double、char → int など)。boolean は他型へも他型からも変換できません。

縮小は自動不可(キャストが必要)

double d = 3.9;
// int n = d;          // NG(コンパイルエラー)
int n = (int) d;       // OK(明示キャスト、3へ切り捨て)
Java

精度や範囲を失う可能性がある縮小は必ずキャストが必要です。キャスト後の値の意味(丸め・オーバーフロー)を理解した上で行いましょう。


数値昇格(演算前の型統一)

整数演算は最低でも int

byte a = 10;
byte b = 20;
// byte s = a + b;      // NG(式は int に昇格)
int s = a + b;           // OK
Java

byte/short/char の演算はまず int に昇格します。代入先が小さい型なら、必要に応じてキャストします。

byte s2 = (byte) (a + b); // 値が 127 を超えるとオーバーフローに注意
Java

混在型は「より広い型」へ

int i = 3;
long l = 4L;
double d = 0.5;

System.out.println(i + l);    // 結果は long
System.out.println(l + d);    // 結果は double
System.out.println(1 / 2);    // 0(int / int → 整数除算)
System.out.println(1 / 2.0);  // 0.5(double が含まれるため浮動小数演算)
Java

型が混在する式では、より広い型に揃えてから計算されます。整数同士の除算は切り捨てになることを忘れず、必要なら最初から double を混ぜます。


リテラルの型と接尾辞(基礎の落とし穴)

既定の型と接尾辞

long big = 3_000_000_000L; // 整数リテラルは既定で int、long にするなら L
float f = 3.14f;           // 小数リテラルは既定で double、float にするなら f
double d = 3.14;           // 既定の小数は double
Java

整数は既定で int、浮動小数は既定で double。代入先に合わせて Lf を明示すると意図が伝わります。

char と文字コード

char c = 'A';      // 文字リテラル
int code = c;      // 65(Unicode コードポイント)
char jp = '\u3042'; // あ(Unicode エスケープ)
Java

char は 16bit のコード単位(UTF-16)です。BMP 外の文字はサロゲートペアになります(コードポイント操作が必要な場面に注意)。


文字列連結の自動変換

String + 任意型で自動文字列化

String s = "n=" + 42;         // "n=42"
System.out.println(1 + 2 + "A"); // "3A"(左から順に評価)
System.out.println("A" + 1 + 2); // "A12"
System.out.println("A" + (1 + 2)); // "A3"(意図が明確)
Java

+ に String が含まれると、他のオペランドは自動で文字列化されます。評価順の影響が大きいので、曖昧なら括弧で明示します。


オートボクシング/アンボクシング(自動だけど別の仕組み)

プリミティブ ↔ ラッパーの自動変換

Integer ix = 10;    // ボクシング(int → Integer)
int n = ix;         // アンボクシング(Integer → int)
java.util.List<Integer> list = java.util.List.of(1, 2, 3); // コレクションは参照型
Java

コレクションやジェネリクスは参照型のみなので、プリミティブは自動でラッパー型に包まれ/取り出されます。null のアンボクシングは NullPointerException になるので注意。

Integer nx = null;
// int m = nx; // NPE(アンボクシング時)
Java

よくある落とし穴(重要ポイントの深掘り)

精度損失とオーバーフロー

int big = 1_000_000;
int r = big * big;          // オーバーフロー(負になる)
long safe = 1_000_000L * 1_000_000L; // long で計算して回避
Java

演算前に「広い型へ昇格させる」工夫が必要です。少なくとも片方を long や double にして計算しましょう。

整数除算の落とし穴

int a = 1, b = 2;
double x = a / b;         // 0.0(整数除算の結果 0 が double へ)
double y = a / (double) b; // 0.5(片方を double に)
Java

期待が小数なら、演算前に片方を浮動小数へ変換しておくのが安全です。

比較の罠(ラッパーと参照比較)

Integer a1 = 128, a2 = 128;
System.out.println(a1 == a2); // false(参照が別)
System.out.println(a1.equals(a2)); // true(値比較)
Java

ラッパー型は参照。== は参照比較、値比較は equals を使います(-128〜127 はキャッシュにより == でも同値に見える場合があり、逆に混乱の元)。


例題で身につける

例 1: 混在型の安全な計算

public class MixedCalc {
    public static void main(String[] args) {
        int qty = 3;
        long unit = 1_000_000_000L;
        long total = qty * unit; // int が long に昇格 → 安全
        System.out.println(total);
    }
}
Java

例 2: 整数除算を小数へ

public class DivSafe {
    public static void main(String[] args) {
        int a = 1, b = 2;
        double r1 = a / (double) b;  // 0.5
        double r2 = (double) a / b;  // 0.5(どちらでも可)
        System.out.println(r1 + ", " + r2);
    }
}
Java

例 3: ループでの昇格とキャスト

public class SumBytes {
    public static void main(String[] args) {
        byte[] arr = {100, 27, 1};
        int sum = 0;               // まず int で受ける
        for (byte v : arr) sum += v; // 演算は int 昇格
        byte limited = (byte) Math.min(sum, 127); // 代入時だけ必要ならキャスト
        System.out.println(sum + " / " + limited);
    }
}
Java

仕上げのアドバイス(重要部分のまとめ)

  • 拡大変換は自動、縮小はキャストが必要。boolean は変換不可。
  • 演算前の数値昇格ルールを理解する(byte/short/char → int、混在は広い型へ)。
  • リテラルの既定型(int/double)と接尾辞(L/f)で意図を明確に。
  • 文字列連結は自動文字列化されるが、評価順で結果が変わるため括弧で明示。
  • オートボクシング/アンボクシングは便利だが、null と == の罠に注意。
  • 精度損失・オーバーフローを避けるため、計算前に十分な広さの型にしてから演算する。

タイトルとURLをコピーしました