我发现this article在旧式函数与新Java-8 lambda函数和并行处理的比较中非常有用。我无法理解的一件事是对lambda函数的一个限制:从第4页开始:
3.3前提条件 尽管lambda表达式更有意义 cise替代 AIC ,他们不是一个完整的替代品。 有几个先决条件 LambdaFicator 检查 在重构之前 AIC 成为一个lambda表达式。这些 前提条件是lambda表达式的固有特性 用Java实现,而不是我们工具的限制。 (P1) AIC 必须从接口实例化。实例 抽象或具体类不能转换为lambda 表达式。 (P2) AIC 必须没有字段,并且只声明一个方法。 lambda表达式表示单个匿名函数 重刑;因此,一个 AIC 用多种方法不能 转换为单个lambda表达式。 (P3) AIC 一定不能参考 这个 要么 超 。在 一个lambda表达式, 这个 和 超 是词汇范围的, 意思是他们的解释就像在他们身上一样 封闭环境,例如,好像它们出现在国家一样 - 在lambda表达之前[6]。但是,在一个 AIC 他们指的是内在阶级本身。 (P4) AIC 不得声明递归方法。为了 执行递归调用,我们必须获得一个引用 匿名功能。而 LambdaFicator 可以表演 这种重构,这可能会带来不必要的复杂性 进入代码并损害可理解性。
在P4上," AIC不能声明递归方法...... LambdaFicator可以执行这种重构......",如何重构lambda表达式来引用自身?根据定义,这些lambda匿名函数没有可以引用的名称,也没有引用自己(上面的P3)。?
答案 0 :(得分:2)
public class Test {
static Runnable r;
public static void main(String... args) {
r = () -> r.run();
r.run();
}
}
Runnable
在运行时从字段r
获取对自身的引用。
如果您不想添加字段,也可以使用长度为1的数组来存储引用。
答案 1 :(得分:1)
来自@ Alex的回答:
@FunctionalInterface
public interface SelfRunnable extends Runnable {
public void run(SelfRunnable this_);
@Override
public default void run() {
run(this);
}
public static Runnable runnable(SelfRunnable runnable) {
return runnable;
}
}
public interface Test {
public static void main(String... arguments) {
final Runnable r = SelfRunnable.runnable(this_ -> this_.run());
r.run();
}
}
答案 2 :(得分:1)
正如here所述,Java实现递归函数的规范方法是方法:
public static int fib(int n) {
return n==0? 0: n==1? 1: fib(n-1)+fib(n-2);
}
然后,如果您需要一个实现功能 interface
的实例,您可以使用方法参考:
Function<Integer, Integer> fib = MyClass::fib;
或
IntUnaryOperator fib0=MyClass::fib;
这是与lambda表达式最接近的等价物,因为lambda表达式不仅仅是用于替换匿名内部类的运行时生成的类的语法糖,而且还用于托管要实现的单个抽象方法的代码的匿名方法。
使用普通的递归方法将匿名方法转换为命名方法,同时保留lambda表达式的所有其他属性。这与尝试给lambda表达式引用自身的所有其他变通方法不同,例如将实例存储到字段中。这些变通方法在语义上并不等效(效率较低)。