Java 類型轉換全解析:從自動提升到精度陷阱
一、基本類型轉換規則
| 方向 | 規則 | 示例 | 風險 |
| 自動類型提升 (Widening) | 容量小 → 容量大,無需代碼,編譯器隱式完成 | int → long → float → double
byte → short → int
char → int | 無數據丟失,但 int→float、long→float/double 可能損失精度 |
| 強制類型轉換 (Narrowing) | 容量大 → 容量小,必須显式 (目標類型)值 | double d=3.14; int i=(int)d; // i=3
long l=130; byte b=(byte)l; // b=-126 (溢出) | 截斷小數、高位截斷溢出、符號位改變 |
二、運算中的隱式提升
byte a = 10, b = 20;
int c = a + b; // byte/short/char 參與運算**自動提升為 int**
long d = a + 10L; // 有 long 參與,整體提升為 long
float e = a + 1.0f; // 有 float,提升為 float
double f = a + 1.0; // 默認 double,提升為 double
三、精度丟失經典場景
- 浮點數賦值給整數:
int i = (int) 3.99; // 3,直接截斷,不四捨五入。
- 大整數轉小類型溢出:
int big = 130; byte b = (byte) big; // -126(二進制截取低 8 位)。
- 浮點運算固有誤差:
System.out.println(0.1 + 0.2); // 0.30000000000000004 → **金額計算必須用 BigDecimal**。
long → float/double:long 64 位精度,float 只有 24 位有效尾數,超過 224 會丟失精度。
四、包裝類與字符串轉換
| 轉換 | API | 注意 |
| 基本類型 → String | String.valueOf(i) / i + "" / Integer.toString(i) | 推薦 String.valueOf(null 安全) |
| String → 基本類型 | Integer.parseInt("123") / Double.parseDouble("3.14") | 異常 NumberFormatException 需捕獲 |
| 基本類型 ↔ 包裝類 | 自動拆裝箱 (JDK 1.5+) | 緩存範圍:Integer -128~127,超出新建對象 |
| 包裝類 → String | obj.toString() | obj 為 null 拋 NPE,用 String.valueOf(obj) 安全 |
五、實戰最佳實踐
- 金額/精度敏感場景:全鏈路使用
BigDecimal(構造器用 String 參數),setScale(2, RoundingMode.HALF_UP) 保留兩位四捨五入。
- 避免無意識窄化:編譯器報錯時別盲目加強轉,**先確認數值範圍是否安全**。
- 常量定義用 final + 字面量:
final int MAX = 100; 進入常量池,調用處直接內聯。
- 移位運算代替乘除 2 的冪次:
x << 3 ≡ x * 8,x >> 1 ≡ x / 2(負數右移保留符號位)。
- 單元測試覆蓋邊界值:
Byte.MAX_VALUE、Integer.MIN_VALUE、Double.NaN 等特殊值。
六、總結口訣
小變大,自動來;大變小,強制改。
浮點變整數,小數點後全砍掉。
大數塞小盒,溢出符號反了號。
金額計算用BigDecimal,浮點誤差不再惱。