Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/309.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java堆栈和递归_Java_Recursion_Design Patterns_Stack_History - Fatal编程技术网

Java堆栈和递归

Java堆栈和递归,java,recursion,design-patterns,stack,history,Java,Recursion,Design Patterns,Stack,History,我的问题是关于Java堆栈的设计。它的设计是否考虑了递归,或者递归是否因堆栈的结构而成为一种东西?一个明显的非答案: 实际上,递归的“真正意义”在于,编译器认识到这一点,并在封面下将其优化为迭代循环 令人惊讶的是:Java并没有做到这一点。因此,在现实世界中,递归和Java不能很好地结合在一起。只有几千个递归调用可能会使JVM崩溃。所以,在真正的java中,您绝对要避免递归。对于孤立的小问题来说,这是一件好事。但除此之外,递归在Java中“不是”一件事 堆栈的设计可能更多地基于20年前为虚拟机创

我的问题是关于Java堆栈的设计。它的设计是否考虑了递归,或者递归是否因堆栈的结构而成为一种东西?

一个明显的非答案:

实际上,递归的“真正意义”在于,编译器认识到这一点,并在封面下将其优化为迭代循环

令人惊讶的是:Java并没有做到这一点。因此,在现实世界中,递归和Java不能很好地结合在一起。只有几千个递归调用可能会使JVM崩溃。所以,在真正的java中,您绝对要避免递归。对于孤立的小问题来说,这是一件好事。但除此之外,递归在Java中“不是”一件事


堆栈的设计可能更多地基于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你是对的,我将修改答案。肯定是一个很好的答案:-)