Java堆栈和递归
我的问题是关于Java堆栈的设计。它的设计是否考虑了递归,或者递归是否因堆栈的结构而成为一种东西?一个明显的非答案: 实际上,递归的“真正意义”在于,编译器认识到这一点,并在封面下将其优化为迭代循环 令人惊讶的是:Java并没有做到这一点。因此,在现实世界中,递归和Java不能很好地结合在一起。只有几千个递归调用可能会使JVM崩溃。所以,在真正的java中,您绝对要避免递归。对于孤立的小问题来说,这是一件好事。但除此之外,递归在Java中“不是”一件事Java堆栈和递归,java,recursion,design-patterns,stack,history,Java,Recursion,Design Patterns,Stack,History,我的问题是关于Java堆栈的设计。它的设计是否考虑了递归,或者递归是否因堆栈的结构而成为一种东西?一个明显的非答案: 实际上,递归的“真正意义”在于,编译器认识到这一点,并在封面下将其优化为迭代循环 令人惊讶的是:Java并没有做到这一点。因此,在现实世界中,递归和Java不能很好地结合在一起。只有几千个递归调用可能会使JVM崩溃。所以,在真正的java中,您绝对要避免递归。对于孤立的小问题来说,这是一件好事。但除此之外,递归在Java中“不是”一件事 堆栈的设计可能更多地基于20年前为虚拟机创
堆栈的设计可能更多地基于20年前为虚拟机创建一个简单、易于移植的系统的想法。而且这两个概念(堆栈和递归)都早在Java v1发布之前就存在了。Java8添加了lambda表达式和函数接口,如下所述: 这允许我们定义自己的尾部递归接口:
@FunctionalInterface
public interface TailCall {
TailCall apply();
default boolean isComplete() {
return false;
}
default T result() {
throw new Error("not implemented");
}
default T invoke() {
return Stream.iterate(this, TailCall::apply)
.filter(TailCall::isComplete)
.findFirst()
.get()
.result();
}
}
因此,你可以这样做:
public class Factorial{
public static TailCall factorialTailRec(final int factorial, final int number) {
if (number == 1)
return TailCalls.done(factorial);
else
return call(() -> factorialTailRec(factorial * number, number - 1));
}
}
然而,Java本身并没有考虑任何尾部递归优化。与Scala(我认为更好的Java)相比,Scala具有@tailrec
注释,因此,当提供此提示并假定该函数是真正的tailrec函数时,编译器将以非递归方式优化递归
@tailrec
def gcd(a: Int, b: Int): Int = …
请在此链接中查看更多详细信息:递归是几乎每种比FORTRAN更新的计算机语言的基本设计原则。调用堆栈是包括FORTRAN在内的更多语言的常见实现技术。实际上,您需要3个堆栈来模拟(即使只有几乎3个堆栈)所有类型的递归(河内的塔楼)。但问题的关键是:“模拟”。为什么要模拟并让编译器从递归的aproach创建一些非递归的东西?尽管Java强调(或强调)是有原因的因此,您可以递归,但java不会将给定的递归代码复杂地重构为非递归代码。java 8没有添加任何尾部递归接口或对TCO的特定支持,您链接的博客也没有这样说。但是,随着java 8中lambdas的引入,程序员可以模拟带尾部调用优化的e递归。这种模拟是一种编程技术,而不是语言功能。@JohnBollinger你是对的,我将修改答案。肯定是一个很好的答案:-)