A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© mengxiang1993 中级黑马   /  2015-2-22 18:39  /  5261 人查看  /  29 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

如果递归调用,形参不是重名了吗?
我记得局部变量好像不可以重名的。
还有就是递归会造成栈内存和什么内存溢出呢?

评分

参与人数 1技术分 +1 收起 理由
万合天宜 + 1 加油

查看全部评分

29 个回复

正序浏览
lwj123 发表于 2015-2-23 12:21
形参只是一个接收数据的一个东西,最重要的是你在递归里改变的作为递归调用的实参不同即可。
每一次递归 ...

我现在就是想知道到底是哪块的内存溢出了?静态方法是存在方法区?
回复 使用道具 举报
过来看看
回复 使用道具 举报
mengxiang1993 发表于 2015-2-23 10:24
方法区,也叫静态域。存放在对象中用static定义的静态成员(即静态变量,同理,如果该静态变量是基本类型 ...

new出的对象存在堆中。被static修饰的成员存在方法区中,方法区分静态和一般。
这些所做的仅仅是把数据存起来。
存好之后,要开始运算。运算都是在栈内存的main中,因为它是程序的入口。存储和运算是分开的。

我是猜想的。你可以继续思考,不要受我影响。
回复 使用道具 举报
因为一直调用自己会不停创建新的空间,所以当内存不够时,就会出现内存溢出。
回复 使用道具 举报
形参名字是什么不重要的,一个函数循环递归,会不断消耗系统资源啊,内存是有限的
回复 使用道具 举报
lwj123 发表于 2015-2-23 12:21
形参只是一个接收数据的一个东西,最重要的是你在递归里改变的作为递归调用的实参不同即可。
每一次递归 ...

搜嘎~~了解了解了
回复 使用道具 举报
万合天宜 发表于 2015-2-22 19:30
形参只是用来传递的吧,关键是实参不同,这块我也不太清楚哦。还有堆栈溢出是因为递归次数太多了,一般递归 ...

形参只是一个接收数据的一个东西,最重要的是你在递归里改变的作为递归调用的实参不同即可。
每一次递归都会开辟一段新的内存空间,如果次数过多,就不宜做递归,这样会发生内存溢出
回复 使用道具 举报
sofeel 发表于 2015-2-23 00:12
一,先谈参数。
形参、实参都是参数,不同在于实参是有具体指向的引用,形参需要实参来激活。当实参把自己 ...

方法区,也叫静态域。存放在对象中用static定义的静态成员(即静态变量,同理,如果该静态变量是基本类型则将变量名和值存入静态域,如果是引用类型则指向new出的对象)。静态方法也存在方法区?
为什么还分main方法区?
回复 使用道具 举报
alvis2015 发表于 2015-2-23 09:19
看代码

上面这段代码也是递归,递归方法中没有声明变量,但内存仍会溢出。

按说方法内存是存放在方法区中的,具体我也不懂得,总之方法在调用的时候,会在栈内存总开辟一段空间用于方法的运行。内存这个地方我也还有些不懂,共同学习。嘿嘿
回复 使用道具 举报
alvis2015 发表于 2015-2-23 09:07
栈内存溢出的原因好像是递归函数每一次调用,都要在内存中开辟出一个空间来,如果递归不返回的话,就会一 ...

看代码
  1. public static void test(){
  2.       test();
  3. }
复制代码

上面这段代码也是递归,递归方法中没有声明变量,但内存仍会溢出。
内存溢出的原因你就明白了

点评

大概明白了,但是这里的内存是方法区内存吗?  发表于 2015-2-23 10:20
回复 使用道具 举报
mengxiang1993 发表于 2015-2-22 21:16
那么造成栈内存溢出的原因是什么?难道不是一直在产生新的局部变量吗? ...

栈内存溢出的原因好像是递归函数每一次调用,都要在内存中开辟出一个空间来,如果递归不返回的话,就会一直在栈内存中开辟新的空间,这个过程中没有产生新的局部变量,局部变量仍然只有你在函数体中声明的一个,而在每次调用递归函数体的时候,在内存中函数的参数值是固定的,是你声明的变量的值传递进去的。
回复 使用道具 举报
mengxiang1993 发表于 2015-2-22 21:47
嗯,这会涉及到同一个方法局部变量重名吧,这个怎么解释?

每次函数调用都开辟新空间,怎么会互相干扰呢?就好比有2个叫张三的学生,只要他们在不同的班级,老师上课点名就不会遇到重名问题。所以同名变量不要紧,只要他们是存放于不同位置的即可
回复 使用道具 举报
内存溢出补充下:
       String s="",  大家都知道“”这是一个String类型的对象,它是有自己空间的。递归过程中虽然始终只有一个变量,存在于最初的方法体中。可仍然有内存溢出的危险,原因在于:函数体有自己的空间,尽管除了第一个函数体外的函数体是空的,就像那个空字符串一样。
      函数体是空的,为什么依然会开辟空间呢?因为数据有可能会在该空间内参与运算。如果变量经过该空间后,能活着回来,变量会路过这里,即会在此间参与运算;如果变量经过该空间后,死在了外面,程序就挂了,那这空间算是白开了这么久!
回复 使用道具 举报
一,先谈参数。
形参、实参都是参数,不同在于实参是有具体指向的引用,形参需要实参来激活。当实参把自己的引用对象介绍给形参时,形参也开始指向了该对象。形参的生命周期依赖于所寄生的函数,而函数被调用后会在main方法区内开辟空间,main方法是静态的,即空间是限量的。递归的原理是,当前的函数体没执行完,又调用了一次....,那么,直到递归的条件不满足时,才会罢休,依次关闭倒数第一个方法体,第二个方法体.......直到关闭最初的那个方法体。请问:形参被激活时的方法体时那个?最初的那个方法体。这个形参是生的早死的迟,显然,它是递归过程中的“全局变量”。
二、内存溢出问题。
最初创建的方法体不会关闭,直到递归条件探底,众多的方法体才会倒着相继执行结束而关闭。那么,这个递归条件就必须有限制,才能防止内存溢出。

点评

方法体和内存的关系是?能具体说下什么内存吗?  发表于 2015-2-23 10:28
回复 使用道具 举报
本帖最后由 wdhm5423 于 2015-2-23 09:04 编辑

public class digui {
public static void main(String[] args) throws InterruptedException{
  hanshu(1);
}

public static int hanshu(int n) throws InterruptedException{
  System.out.println(n);
  int m=n+1;
  Thread.sleep(1000);//等一秒
  return hanshu(m);
  
}
}
重新写了个递归,引用五楼说的
在递归方法中:
         方法括号内的整体叫做形参,这个参数作为一个变量只在方法中声明了一次。
         在递归调用的过程中,这个变量的值(即实际参数)传递给形参(即括号内)。
形参只创声明了一次,其他都是实参的值传给形参。
上面代码中,你是否理解为局部变量m每次递归都会创建,所以重名?
这里局部变量的作用域只是在当前实参值m传给形参的函数内有效。下一次递归,就是换了一个实参值(m+1),重新定义的局部变量m也只是在当前实参值(m+1)传给形参的函数内有效,这就变成了两个不同的局部(也就是作用域),局部变量不重名是在同一个作用域内不重名,所以不存在重名的说法。
回复 使用道具 举报
mengxiang1993 发表于 2015-2-22 21:46
为什么跟形参没关系呢?形参属于局部变量,会在栈内存中开辟内存吧

我这边太懒了,直接用main递归,定义了个静态变量作为参数,每次调用不会另外开辟内存。
回复 使用道具 举报
我是来看答案的。
回复 使用道具 举报
fantacyleo 发表于 2015-2-22 21:26
每次递归调用,都会在栈中开辟新空间,用于保存新的局部变量值,栈的长度于是不断增长,超过一定长度就产生 ...

嗯,这会涉及到同一个方法局部变量重名吧,这个怎么解释?
回复 使用道具 举报
wdhm5423 发表于 2015-2-22 21:37
递归过程,变量在内存中堆栈,难以释放。

以上例子中,递归每次创建4M字节,作为一个变量堆在栈内存中不能 ...

为什么跟形参没关系呢?形参属于局部变量,会在栈内存中开辟内存吧
回复 使用道具 举报
12下一页
您需要登录后才可以回帖 登录 | 加入黑马