Switch语句-JVM内存分配,堆栈溢出

问题描述 投票:0回答:1

我正在学校上Java课。我们分配了这个课程来设计一个类,充当一个带有几个子菜单的菜单。

结构有点像这样(下面的伪代码,只是为了显示结构):

public static void mainMenu() {

switch(integer variable){

case 1: submenu1();
break;
case 2: submenu2();
break;
}
}



public static void submenu1() {

switch(integer variable){

case 1: subsubmenu1();
break;
case 2: subsubmenu2();
break;
default: mainMenu(
}
}


public static void subsubmenu1() {

switch(integer variable) {
case 1:  anothersubmenu1()
break;
case 2:  anothersubmenu2();
break;
default: submenu1();
}
}

我的问题是:我的老师说的是错误的,因为如果我这样做的话,JVM将程序从一个地方到另一个地方的路径存储在内存中,从长远来看,这将导致堆栈溢出。他还没有完全解释它,他只是说我应该使用一个布尔变量将while循环括起来,并添加一个选项来翻转该布尔值以退出while循环,因为这种方式Java不会存储程序从一种方法转移到另一种方法的路径。

再次,他没有详细解释它,这听起来使他解释它的方式非常混乱(我试图根据他给我的信息尽可能清楚地使它清晰起来)。我一直在网上寻找最近​​3个小时内与他告诉我的内容类似的内容,但找不到任何内容...因此,我决定向专家询问。

你们能帮我吗?

java
1个回答
1
投票

是,您的老师是(部分)正确的。关键部分是您可能会从mainMenu()内部调用submenu1(),而又可能会从submenu1()内部调用subsubmenu1()。如果您每次都在mainMenu()中时调用submenu1(),而每次在submenu1()中时都调用mainMenu(),则程序将崩溃。

对于每个函数调用,底层系统都需要为函数的局部变量等保留内存。这就是所谓的堆栈框架。当您从自身内部(直接或间接)调用函数时,它称为recursion。递归需要在某个时候返回。如果不是这样,则会因为内存用完而导致堆栈溢出。


0
投票

[计算机执行方法/功能调用时,它必须:

  1. [记住调用函数在做什么-局部变量的值,以及被调用函数完成后在哪里恢复执行;
  2. 将控件转移到调用的函数。

当调用的函数完成时,它:

  1. 将控制权返回到调用函数中的记忆位置;在那里,它
  2. 还原局部变量的值,等等;和
  3. 使用从被调用函数返回的值继续处理。

您的函数系统的问题在于它们只能继续调用而永不返回:

[mainMenu-> submenu1-> mainMenu-> subMenu1 ...等,等等。

如果函数永不返回,则每次调用新函数时都必须记住越来越多的东西,可能在某个时候超过了可用于存储该东西的(堆栈)内存量,从而导致堆栈溢出错误。

某些语言实现了称为“尾部调用优化”的优化,当调用另一个函数是您的函数可以执行的last时,实际上将避免存储那些东西。在这种情况下,它不再需要局部变量的值,也不需要记住要恢复的位置,因为它可以在已记住的its调用函数中恢复。

在这样的语言中,您的代码实际上可以正常运行,但是java并不是其中的一种。

© www.soinside.com 2019 - 2024. All rights reserved.