流程控制與運算符是程式邏輯的骨架。本文系統整理 Java 所有控制結構、運算符優先級、型別轉換規則,並提供實戰範例與常見陷阱。
// if-else 鏈
if (score >= 90) grade = 'A';
else if (score >= 80) grade = 'B';
else if (score >= 70) grade = 'C';
else grade = 'D';
// switch-case (Java 12+ 表達式寫法)
String dayName = switch (day) {
case 1, 2, 3, 4, 5 -> "工作日";
case 6, 7 -> "週末";
default -> throw new IllegalStateException("無效日期: " + day);
};
// switch 傳統語句 (穿透特性)
switch (month) {
case 12: case 1: case 2: season = "冬季"; break;
case 3: case 4: case 5: season = "春季"; break;
// ...
}
// for 迴圈 (三段式)
for (int i = 0; i < 10; i++) { ... }
// 增強 for (for-each) - 僅讀遍歷
for (String item : list) { ... }
// while - 先判斷
while (condition) { ... }
// do-while - 至少執行一次
do { ... } while (condition);
// 標籤配合 break/continue 控制外層迴圈
outer: for (int i = 0; i < 3; i++) {
inner: for (int j = 0; j < 3; j++) {
if (j == 1) break outer; // 跳出外層
}
}
try (Resource r = new Resource()) { // try-with-resources 自動關閉
riskyOperation();
} catch (SpecificException e) {
handleSpecific(e);
} catch (Exception e) {
handleGeneral(e);
} finally {
cleanup(); // 無 try-with-resources 時必要
}
| 陷阱 | 錯誤代碼 | 正確做法 |
|---|---|---|
| 整數除法截斷 | int r = 5 / 2; // 2 | double r = 5.0 / 2; // 2.5 |
| 溢位 | int x = 2_000_000_000; x * 2 → 負數 | long x = 2_000_000_000L; 或 Math.multiplyExact() |
| 浮點精度 | 0.1 + 0.2 == 0.3 → false | BigDecimal 或誤差範圍比較 |
| 自增副作用 | int a=1; int b = a++ + ++a; // 混亂 | 拆分語句,避免單表達式多次修改同變數 |
// 權限掩碼 int READ = 1 << 0; // 0001 = 1 int WRITE = 1 << 1; // 0010 = 2 int EXEC = 1 << 2; // 0100 = 4 int permission = READ | WRITE; // 0011 = 3 boolean canRead = (permission & READ) != 0; permission |= EXEC; // 新增執行權限 permission &= ~WRITE; // 移除寫入權限 // 快速乘除 2 的冪次 int n = 10; n << 3; // n * 8 = 80 n >> 2; // n / 4 = 2 // 判斷奇偶 (n & 1) == 1 // 奇數 (n & 1) == 0 // 偶數 // 交換兩數 (無需暫存變數) a ^= b; b ^= a; a ^= b;
// 傳統寫法
if (obj instanceof String) {
String s = (String) obj; // 需要強轉
System.out.println(s.length());
}
// Java 16+ 模式匹配:直接宣告並轉型
if (obj instanceof String s) {
System.out.println(s.length()); // s 直接可用
}
// 在 switch 中使用 (Java 17+)
String formatted = switch (obj) {
case Integer i -> "整數: " + i;
case String s -> "字串: " + s;
case null -> "空值";
default -> "其他: " + obj.getClass().getSimpleName();
};
// 規則:若第二、三操作數型別不同,按數值提升規則推導共同型別 // 基本型別:提升至較大型別 (int + double → double) // 參考型別:尋找共同父類/介面 // 一邊是 null:型別為另一邊 Integer a = 10; Double b = 20.0; Number result = true ? a : b; // Number (共同父類) String s = true ? "hello" : null; // String // String s = true ? null : "hello"; // 也是 String
Scanner sc = new Scanner(System.in);
// 讀整行 (含空白)
String line = sc.nextLine();
// 正則分隔符
sc.useDelimiter("\\s*,\\s*"); // 以逗號分隔,忽略前後空白
while (sc.hasNext()) {
String token = sc.next();
}
// 輸入驗證
if (sc.hasNextInt()) {
int num = sc.nextInt();
} else {
String garbage = sc.next(); // 消耗無效輸入
}
| 格式 | 說明 | 範例輸出 |
|---|---|---|
| %d | 十進位整數 | 42 |
| %05d | 補零寬度 5 | 00042 |
| %f | 浮點數 (預設 6 位小數) | 3.141593 |
| %.2f | 保留 2 位小數 | 3.14 |
| %s | 字串 | Hello |
| %-10s | 左對齊寬度 10 | Hello |
| %c | 字元 | A |
| %b | 布林 | true |
| %n | 平台換行符 | \n 或 \r\n |
| %tF | 日期 (yyyy-MM-dd) | 2024-01-15 |
| %tT | 時間 (HH:mm:ss) | 14:30:00 |
System.out.printf("姓名: %-10s 年齡: %3d 分數: %6.2f%%%n", "張三", 18, 98.5);
// 輸出: 姓名: 張三 年齡: 18 分數: 98.50%
import java.util.Scanner;
public class Calculator {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("簡易計算機 (輸入 q 退出)");
while (true) {
System.out.print("\n運算式 (如: 3 + 5): ");
String line = sc.nextLine().trim();
if ("q".equalsIgnoreCase(line)) break;
try {
String[] parts = line.split("\\s+");
if (parts.length != 3) throw new IllegalArgumentException("格式錯誤");
double a = Double.parseDouble(parts[0]);
String op = parts[1];
double b = Double.parseDouble(parts[2]);
double result = switch (op) {
case "+" -> a + b;
case "-" -> a - b;
case "*" -> a * b;
case "/" -> {
if (b == 0) throw new ArithmeticException("除數不能為零");
yield a / b;
}
case "%" -> a % b;
default -> throw new IllegalArgumentException("不支援運算子: " + op);
};
System.out.printf("結果: %.2f %s %.2f = %.4f%n", a, op, b, result);
} catch (Exception e) {
System.out.println("錯誤: " + e.getMessage());
}
}
System.out.println("再見!");
}
}
Math.abs(a-b) < EPSILONObjects.equals(a, b) 避免 NPE扎實掌握流程控制與運算符,是寫出正確、高效、可維護 Java 代碼的基石。建議將運算符優先級表、格式化參考表列印貼在工位,遇到疑問隨時查閱,久而久之自然內化為直覺。