一种方法是编写一个辅助函数helper,它接受一个函数和一个数字作为参数,然后编写你真正想要的函数fact = helper(helper,x)。
像这样:
BiFunction<BiFunction, Double, Double> factHelper =
(f, x) -> (x == 0) ? 1.0 : x*(double)f.apply(f,x-1);
Function<Double, Double> fact =
x -> factHelper.apply(factHelper, x);
在我看来,这比依赖极端情况语义(如捕获对可变结构的引用的闭包)或允许自我引用并警告“可能未初始化”的可能性要稍微优雅一些。
由于 Java 的类型系统,这仍然不是一个完美的解决方案——泛型不能保证 f 的参数 factHelper 与 factHelper 的类型相同(即相同的输入类型和输出类型),因为这将是一个无限嵌套的泛型。
因此,一个更安全的解决方案可能是:
Function<Double, Double> fact = x -> {
BiFunction<BiFunction, Double, Double> factHelper =
(f, d) -> (d == 0) ? 1.0 : d*(double)f.apply(f,d-1);
return factHelper.apply(factHelper, x);
};
factHelper 不完美的泛型类型产生的代码异味现在包含(或者,我敢说,封装)在 lambda 中,确保永远不会在不知情的情况下调用 factHelper。