我正在学校上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个小时内与他告诉我的内容类似的内容,但找不到任何内容...因此,我决定向专家询问。
你们能帮我吗?
是,您的老师是(部分)正确的。关键部分是您可能会从mainMenu()
内部调用submenu1()
,而又可能会从submenu1()
内部调用subsubmenu1()
。如果您每次都在mainMenu()
中时调用submenu1()
,而每次在submenu1()
中时都调用mainMenu()
,则程序将崩溃。
对于每个函数调用,底层系统都需要为函数的局部变量等保留内存。这就是所谓的堆栈框架。当您从自身内部(直接或间接)调用函数时,它称为recursion。递归需要在某个时候返回。如果不是这样,则会因为内存用完而导致堆栈溢出。
[计算机执行方法/功能调用时,它必须:
当调用的函数完成时,它:
您的函数系统的问题在于它们只能继续调用而永不返回:
[mainMenu-> submenu1-> mainMenu-> subMenu1 ...等,等等。
如果函数永不返回,则每次调用新函数时都必须记住越来越多的东西,可能在某个时候超过了可用于存储该东西的(堆栈)内存量,从而导致堆栈溢出错误。
某些语言实现了称为“尾部调用优化”的优化,当调用另一个函数是您的函数可以执行的last时,实际上将避免存储那些东西。在这种情况下,它不再需要局部变量的值,也不需要记住要恢复的位置,因为它可以在已记住的its调用函数中恢复。
在这样的语言中,您的代码实际上可以正常运行,但是java并不是其中的一种。