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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

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

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

评分

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

查看全部评分

29 个回复

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

形参就是局部变量啊,会在栈内存中声明变量,名字相同难道也可以,一般在一个方法内,声明相同的名字的局部变量,会报错的
回复 使用道具 举报
我是看评论的
回复 使用道具 举报
mengxiang1993 发表于 2015-2-22 19:50
形参就是局部变量啊,会在栈内存中声明变量,名字相同难道也可以,一般在一个方法内,声明相同的名字的局 ...

我说说我的看法吧,不知道对不对,仅供参考:
形式类型:是你在定义方法时括号里面的参数。
如:public void setName(String name){this.name = name;}
name:就是形式参数。

实际类型:在调用方法是传进去的参数。
如: setName("张三");
"张三":就是实际类型。

形参首先是个参数,变量是一个值可以改变的量。
在递归方法中:
         方法括号内的整体叫做形参,这个参数作为一个变量只在方法中声明了一次。
         在递归调用的过程中,这个变量的值(即实际参数)传递给形参(即括号内)。
也就是说递归是在说一个过程,是一个自己调用自己的过程,而不是循环声明变量。

评分

参与人数 1技术分 +1 收起 理由
万合天宜 + 1 很给力!

查看全部评分

回复 使用道具 举报
楼上说的有道理。。。。。。。。。。。
回复 使用道具 举报
alvis2015 发表于 2015-2-22 20:46
我说说我的看法吧,不知道对不对,仅供参考:
形式类型:是你在定义方法时括号里面的参数。
如:public vo ...

那么造成栈内存溢出的原因是什么?难道不是一直在产生新的局部变量吗?
回复 使用道具 举报
每次递归调用,都会在栈中开辟新空间,用于保存新的局部变量值,栈的长度于是不断增长,超过一定长度就产生溢出了
回复 使用道具 举报
本帖最后由 wdhm5423 于 2015-2-22 21:53 编辑

递归过程,变量在内存中堆栈,难以释放。
  1. public class digui {
  2.         static String[] str={"1"};
  3.         public static void main(String[] args){
  4.                 byte[] b=new byte[1024*1024*4];//每次创建4M的字节
  5.                 main(str);//递归
  6.         }
  7. }
复制代码

以上例子中,递归每次创建4M字节,作为一个变量堆在内存中不能释放,我电脑4G,4G/4M=1024次,运行2、3秒报内存溢出。
异常:Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
这就是一个内存溢出的例子,递归次数太多会造成内存溢出,所以递归过程要考虑内存溢出问题(此处跟形参没有关系)。
回复 使用道具 举报
wdhm5423 发表于 2015-2-22 21:37
递归过程,变量在内存中堆栈,难以释放。

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

为什么跟形参没关系呢?形参属于局部变量,会在栈内存中开辟内存吧
回复 使用道具 举报
fantacyleo 发表于 2015-2-22 21:26
每次递归调用,都会在栈中开辟新空间,用于保存新的局部变量值,栈的长度于是不断增长,超过一定长度就产生 ...

嗯,这会涉及到同一个方法局部变量重名吧,这个怎么解释?
回复 使用道具 举报
我是来看答案的。
回复 使用道具 举报
mengxiang1993 发表于 2015-2-22 21:46
为什么跟形参没关系呢?形参属于局部变量,会在栈内存中开辟内存吧

我这边太懒了,直接用main递归,定义了个静态变量作为参数,每次调用不会另外开辟内存。
回复 使用道具 举报
本帖最后由 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)传给形参的函数内有效,这就变成了两个不同的局部(也就是作用域),局部变量不重名是在同一个作用域内不重名,所以不存在重名的说法。
回复 使用道具 举报
一,先谈参数。
形参、实参都是参数,不同在于实参是有具体指向的引用,形参需要实参来激活。当实参把自己的引用对象介绍给形参时,形参也开始指向了该对象。形参的生命周期依赖于所寄生的函数,而函数被调用后会在main方法区内开辟空间,main方法是静态的,即空间是限量的。递归的原理是,当前的函数体没执行完,又调用了一次....,那么,直到递归的条件不满足时,才会罢休,依次关闭倒数第一个方法体,第二个方法体.......直到关闭最初的那个方法体。请问:形参被激活时的方法体时那个?最初的那个方法体。这个形参是生的早死的迟,显然,它是递归过程中的“全局变量”。
二、内存溢出问题。
最初创建的方法体不会关闭,直到递归条件探底,众多的方法体才会倒着相继执行结束而关闭。那么,这个递归条件就必须有限制,才能防止内存溢出。

点评

方法体和内存的关系是?能具体说下什么内存吗?  发表于 2015-2-23 10:28
回复 使用道具 举报
内存溢出补充下:
       String s="",  大家都知道“”这是一个String类型的对象,它是有自己空间的。递归过程中虽然始终只有一个变量,存在于最初的方法体中。可仍然有内存溢出的危险,原因在于:函数体有自己的空间,尽管除了第一个函数体外的函数体是空的,就像那个空字符串一样。
      函数体是空的,为什么依然会开辟空间呢?因为数据有可能会在该空间内参与运算。如果变量经过该空间后,能活着回来,变量会路过这里,即会在此间参与运算;如果变量经过该空间后,死在了外面,程序就挂了,那这空间算是白开了这么久!
回复 使用道具 举报
mengxiang1993 发表于 2015-2-22 21:47
嗯,这会涉及到同一个方法局部变量重名吧,这个怎么解释?

每次函数调用都开辟新空间,怎么会互相干扰呢?就好比有2个叫张三的学生,只要他们在不同的班级,老师上课点名就不会遇到重名问题。所以同名变量不要紧,只要他们是存放于不同位置的即可
回复 使用道具 举报
mengxiang1993 发表于 2015-2-22 21:16
那么造成栈内存溢出的原因是什么?难道不是一直在产生新的局部变量吗? ...

栈内存溢出的原因好像是递归函数每一次调用,都要在内存中开辟出一个空间来,如果递归不返回的话,就会一直在栈内存中开辟新的空间,这个过程中没有产生新的局部变量,局部变量仍然只有你在函数体中声明的一个,而在每次调用递归函数体的时候,在内存中函数的参数值是固定的,是你声明的变量的值传递进去的。
回复 使用道具 举报
alvis2015 发表于 2015-2-23 09:07
栈内存溢出的原因好像是递归函数每一次调用,都要在内存中开辟出一个空间来,如果递归不返回的话,就会一 ...

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

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

点评

大概明白了,但是这里的内存是方法区内存吗?  发表于 2015-2-23 10:20
回复 使用道具 举报
alvis2015 发表于 2015-2-23 09:19
看代码

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

按说方法内存是存放在方法区中的,具体我也不懂得,总之方法在调用的时候,会在栈内存总开辟一段空间用于方法的运行。内存这个地方我也还有些不懂,共同学习。嘿嘿
回复 使用道具 举报
12下一页
您需要登录后才可以回帖 登录 | 加入黑马