尾遞歸將循環狀態變量轉為函數參數,代碼清晰且無 break 煩擾。但 Java 無尾調用優化(TCO)保證,深度遞歸必導致 StackOverflowError。
靜態編譯器若將尾遞歸轉為循環,會破壞**動態分派語義**。示例:父類 productHelp 為尾遞歸,子類覆寫並在入口檢查參數合法性。靜態優化後,子類檢查邏輯被繞過,導致行為不一致。JIT 動態編譯可在確認無覆寫/最終方法時安全優化,靜態編譯則無法知悉運行時類層次。
public class TailRecursionTest {
private static int loop(int i) { return loop(i); }
public static void main(String[] args) { loop(0); }
}
不要依賴 TCO。 將自然符合尾遞歸模式的算法(如樹遍歷、狀態機)以**顯式循環**實現。雖手工轉換易出錯,但可移植性與可預測性遠超賭 JIT 行為。若極度追求函數式風格,可考慮 Scala/Kotlin 等語言級支持 TCO 的 JVM 語言。