表達式是程式運算的基本單位,由運算子、變數、常值組成。每個表達式在編譯期都有確定的靜態類型,掌握類型推導規則能避免隱式轉型驚喜、精準控制精度與效能。
| 類別 | 運算子代表 | 結果類型 | 備註 |
|---|---|---|---|
| 算術/位元/移位/遞增減 | + - * / % | 數值型(int/long/float/double) | 整數運算預設提升至 int |
| & | ^ ~ | |||
| << >> >>> | |||
| ++ -- | |||
| + - (一元正負號) | |||
| 比較/邏輯 | > < >= <= == != && || ! | boolean | 短路求值 |
| 賦值 | = += -= *= /= %= ... | 左邊變數類型 | 右值會隱式轉型 |
| 條件 (三元) | ? : | 兩分支類型較高者 | 數值型遵循提升規則 |
byte a = 10, b = 20;
int c = a + b; // 正確:a+b 為 int
// byte d = a + b; // 編譯錯誤:int 無法隱式賦值給 byte
byte d = (byte)(a + b); // 需強制轉型
byte、short、char 參與運算先提升為 int,結果為 int。
int n = 10;
int m = 10;
n = (m = 10); // 整個表達式類型為 int,值為 10
// 等同於 m = 10; n = m;
boolean b = false;
boolean b1 = true;
b = (b1 = true); // 類型 boolean,值 true
賦值運算子右結合,整個鏈式賦值表達式的類型 = 最左邊變數類型,值 = 最右邊值。
double d;
d = 10 > 0 ? 1.0 : 2; // 1.0 是 double,2 是 int → 結果提升為 double
規則:若兩分支一為 double、一為 int,int 提升為 double。long + float → float(精度犧牲)。
int a = 5;
double result = a + 3 * 2.0; // 3*2.0 → double,a 提升 → double,最終 double
Java 規定:只有賦值表達式、遞增減表達式、方法呼叫、物件建立 可作為獨立語句(Expression Statement)。
int a = 10;
int b = 20;
a + b; // 編譯錯誤:純運算表達式無副作用,不能獨立成行
a = b; // 合法:賦值表達式
a++; // 合法:遞增表達式
System.out.println(a); // 合法:方法呼叫
new Object(); // 合法:物件建立(雖無引用持有)
| 陷阱 | 錯誤代碼 | 原因 | 修正 |
|---|---|---|---|
| 整數除法截斷 | double avg = sum / count; | sum、count 皆為 int,先做整數除法再轉 double | double avg = (double)sum / count; |
| 三元運算精度損失 | long l = true ? 1 : 1.0; | 結果類型為 double,無法隱式賦值給 long | long l = true ? 1L : 1L; |
| 複合賦值隱式轉型 | byte b = 10; b += 5; | b += 5 等同 b = (byte)(b + 5),含隱式強轉 | 明確認知,或改用 int |
| 浮點比較 | 0.1 + 0.2 == 0.3 | IEEE 754 表示誤差 | Math.abs(a-b) < EPSILON |
int,賦值表達式類型看左邊,三元運算看兩分支較高類型。