現象重現
byte a = 1, b = 2, c = 3;
a = b + c; // 編譯錯誤:無法將 int 隱式轉換為 byte
根本原因
- 整數字面值默認是 int:
1、2、3 在編譯期即為 int,賦值給 byte 時編譯器執行隱式窄化轉換(僅當值在 -128~127 範圍內)。
- 算術運算自動提升:
b + c 觸發 整數提升,兩個 byte 先轉為 int 再相加,結果類型為 int。
- 防止溢出的設計:JLS 規定
byte/short/char 參與運算必須升至 int,避免中間結果超出原類型範圍(如 100+100=200 超過 byte 最大值 127)。
正確寫法
// 方式 1:強制轉型
a = (byte)(b + c);
// 方式 2:使用 Byte 類靜態方法(Java 8+)
a = Byte.parseByte(String.valueOf(b + c)); // 僅示意,實際不推薦
// 方式 3:常量折疊優化(編譯期可確定值)
byte d = 1 + 2; // 編譯器直接計算為 3,屬於常量表達式,允許隱式窄化
對比:c = a + 2 vs c = a + b
| 表達式 | 編譯期類型 | 是否報錯 |
a + 2 | int(字面值 2 為 int) | 需強轉 |
a + b | int(兩 byte 提升) | 需強轉 |
1 + 2 | int(常量折疊為 3) | 不報錯(常量表達式特權) |
最佳實踐
- 涉及
byte/short 運算時,統一使用 int 變量接收結果,最後再按需強轉。
- 位運算(
&、|、^、~)同樣遵循整數提升規則。
- 若確需高性能定點運算,可考慮
int 模擬或引入第三方庫(如 Apache Commons Math)。