迹忆客 专注技术分享

当前位置:主页 > 学无止境 > 编程语言 > Java >

Java 尾部调用优化

作者:迹忆客 最近更新:2023/08/10 浏览次数:

本文讨论尾部调用优化(也称为 TCO)及其在 Java 中不存在的原因。 我们还将看到一些其他可以用来在 Java 中模拟 TCO 的方法。


什么是尾调用优化

尾调用优化是一个过程,我们可以避免为函数分配一个新的堆栈帧,因为调用函数将返回从被调用函数接收的值。

最常见的用途之一是尾递归(一种递归函数,其中函数在末尾调用自身),其中编写递归方法是为了利用尾调用优化,并且可以使用常量堆栈空间。

该方案是在规范中保证任何实现都必须服务于这种优化的编程语言之一。 因此,以下是Scheme编程语言中阶乘方法的两个示例。

示例代码一(无尾递归):

(define (factorial n)
  (if (= n 0) 1
      (* n (factorial (- n 1)))))

示例代码二(带尾递归):

(define (factorial n)
  (define (factorial-tail n accum)
    (if (= n 0) accum
        (factorial-tail (- n 1) (* n accum))))
  (factorial-tail n 1))

在示例代码一中,该函数不是尾递归的。 这是因为每当进行递归调用时(考虑阶乘示例),该方法必须跟踪调用返回后需要对结果执行的乘法。

因此,堆栈如下所示。

(factorial 3)
(* 3 (factorial 2))
(* 3 (* 2 (factorial 1)))
(* 3 (* 2 (* 1 (factorial 0))))
(* 3 (* 2 (* 1 1)))
(* 3 (* 2 1))
(* 3 2)
6

相反,尾递归阶乘的堆栈跟踪如下所示。

(factorial 3)
(factorial-tail 3 1)
(factorial-tail 2 3)
(factorial-tail 1 6)
(factorial-tail 0 6)
6

我们只需要为每次调用 Factorial-tail 跟踪相同的数据。

原因是我们返回一个直接到达顶部的值,这意味着即使我们要调用(阶乘 1000000),我们也只需要与(阶乘 3)所需的空间量相同的空间。

当我们考虑非尾递归阶乘时,情况并非如此,大值可能会导致堆栈溢出。


Java中没有尾部调用优化的原因

目前,在编译器级别,普通 Java 不支持 Java 尾调用优化。 由于继承的存在,找出正在调用的方法可能不是一件容易的事。

另外,现有的堆栈计数机制不允许这种优化很快实现。 也许有理由避免每年语言工作方式发生巨大变化。

第一个原因是尾部调用优化的成本很高。 其次,根据 Java 中的一条规则,每当遇到错误时,我们都会获取堆栈跟踪。

堆栈跟踪是定义明确的概念,几乎无法跟踪每个逻辑调用的一个堆栈帧。 如果 Java 中存在尾调用优化,则这是不可能的。

第三,尾调用优化作为模型是做事的方式,但不是唯一的方式。 一般来说,对于任何可以编写为 TCO 递归应用程序的东西,重构为基于循环的非递归算法并不难。

那么,我们应该做什么呢? 我们可以使用 while 或 for 循环来代替。


有没有办法在Java中模拟尾部调用优化

尽管 Java(虚拟机)具有可以使其他人的工作变得更容易的新功能,但非 Java 编程语言编译到类文件中以在 Java 运行时上执行以支持尾调用优化。

并非每个功能总是合理的,特别是当该语言是最流行的语言之一时。

因此,我们不确定应该使用什么方法在 Java 中使用 TCO; Project Loom 的提案对此进行了很好的解释。

然而,我们认为仍然可以使用一些其他方法来模拟 Java 中的尾调用优化。 第一种是使用其他 JVM 语言,例如 Scala。

第二种解决方案可以使用 lambda 表达式。

上一篇:Java远程调试

下一篇:没有了

转载请发邮件至 1244347461@qq.com 进行申请,经作者同意之后,转载请以链接形式注明出处

本文地址:

相关文章

Java远程调试

发布时间:2023/08/10 浏览次数:123 分类:Java

我们必须执行具有特定参数的 Java 应用程序,以允许远程调试器附加。 我们将探索如何设置运行/调试配置来完成我们的工作。先决条件 要遵循本教程,我们必须启动并运行以下内容。

使用 Java 删除文件夹

发布时间:2023/08/09 浏览次数:76 分类:Java

在本文中,我们将学习如何使用 Java 编程语言删除文件夹/目录。 有多种方法可以做到这一点。 让我们一一看看。使用Java的File类的delete()删除空文件夹

Java 中的多个动作监听器

发布时间:2023/08/09 浏览次数:178 分类:Java

本文我们将介绍如何在 Java 中创建多个动作监听器。在Java中,ActionListener是一个用于处理动作事件的类。 因此,Java 提供了这个接口,使用它我们可以找到用户单击按钮的位置,并生成一些事件

在 Java 中创建通用链表

发布时间:2023/08/09 浏览次数:186 分类:Java

本文我们将介绍如何在 Java 中创建一个通用的单链表。Java LinkedList 简介 LinkedList 是线性数据结构,它将数据存储在随机地址的节点中,并且意味着位于不连续的位置。

在JavaFX中使用setAlignment方法

发布时间:2023/08/09 浏览次数:129 分类:Java

在本文中,我们将了解如何以我们自己的格式对齐 HBox。 我们将看一个例子并逐行解释它以使其更容易理解。在 JavaFX 中使用 setAlignment() 方法

在 JavaFX 中使用 KeyEvent

发布时间:2023/08/09 浏览次数:70 分类:Java

KeyEvent 用于检测按键并在按下按键时执行特定的代码块。本文将展示如何创建按键事件并在用户按下按键时执行简单的代码。 我们还将看到一个简单的示例,以使其更容易理解。

在 JavaFX 中移动对象

发布时间:2023/08/09 浏览次数:199 分类:Java

在本文中,我们将向左、右、上、下四个方向移动对象。 为此,我们将使用以下代码。在 JavaFX 中移动对象 我们看一下下面的代码。 我们稍后会解释。

修复在 JRE 8 中使用 JavaFX 时的访问限制错误

发布时间:2023/08/09 浏览次数:95 分类:Java

本文将讨论如何修复在 JRE 8 中使用 JavaFX 时出现的访问限制错误。此错误主要发生在 Eclipse IDE 中; 我们的解决方案主要基于Eclipse。修复在 JRE 8 中使用 JavaFX 时的访问限制错误

扫一扫阅读全部技术教程

社交账号
  • https://www.github.com/onmpw
  • qq:1244347461

最新推荐

教程更新

热门标签

扫码一下
查看教程更方便