J2SE 1.5 引入可變長度參數 和 Formatter/printf 格式化輸出,極大豐富了方法簽名靈活度與字串格式化能力。本文透過範例展示兩大特性用法與陷阱。
StringBuilder sb = new StringBuilder();
Formatter fmt = new Formatter(sb);
fmt.format("%12.10f", Math.PI); // 寬度12,小數10位
System.out.println(fmt); // 輸出: 3.1415926536
System.out.printf("%12.10f%n", Math.PI); // 直接輸出到標準輸出
String s = String.format("%12.10f", Math.PI); // 取得格式化字串
| 轉換符 | 說明 | 範例輸出 |
|---|---|---|
| %d / %x | 十進位/十六進位整數 | 42 / 2a |
| %f / %e | 定點/科學記號浮點數 | 3.141593 / 3.141593e+00 |
| %s | 字串 (toString) | hello |
| %c | 字元 | A |
| %b | 布林值 | true |
| %n | 平台相關換行符 | \n (Linux) / \r\n (Win) |
| %% | 字面 % 符號 | % |
旗標範例:%,d 千分位分隔 (1,234,567)、%05d 零填寬 (00042)、%-10s 左對齊。
public static void printf(String format, Object... args) { ... }
// 呼叫
printf("Hello %s, %s!", "World", "Java"); // args 為 Object[] { "World", "Java" }
package tigers;
public class FormatPrint {
public static void main(String[] args) {
printf("%, %, % and % are my friends!", "BITAN", "HELEN", "KATHY", "SUSAN");
// 第二次呼叫:4 個佔位符但傳 5 個引數 → 運行時 ArrayIndexOutOfBoundsException
printf("%, %, %, % and % are my favorites", "A", "B", "C", "D");
}
// 簡易 printf:% 佔位符依序替換為 varargs 字串
public static void printf(String msg, String... strs) {
int i = 0;
for (char c : msg.toCharArray()) {
System.out.print(c == '%' ? strs[i++] : c);
}
System.out.println();
}
}
BITAN, HELEN, KATHY and SUSAN are my friends!
A, B, C, D and Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 4
at tigers.FormatPrint.printf(FormatPrint.java:12)
at tigers.FormatPrint.main(FormatPrint.java:6)
第二次呼叫格式字串含 **5 個 %**,但只傳 **4 個字串引數**,導致 strs[4] 存取越界。實務中應檢查引數數量或使用 String.format 由 JDK 內建檢查。
%[argument_index$][flags][width][.precision]conversion
// 範例
System.out.format("%2$d %1$d%n", 10, 20); // 20 10 (引數索引)
System.out.format("%,.2f%n", 1234567.891); // 1,234,567.89 (千分位+2位小數)
System.out.format("%08d%n", 42); // 00000042 (零填寬度8)
varargs 讓 API 更彈性,但需注意重載陷阱與空陣列處理。Formatter/printf 提供 C 風格強大格式化,String.format 更適合構建字串。String.formatted(Object...) 實例方法:"Hello %s".formatted("World"),語法更直觀。