简单问题,不过好像也不简单

wanderForEver 2003-10-07 11:05:52
//test.ScopeTest.java

package test;

public class ScopeTest{

public String getStr(){
String str = new String("asdklajs;di");
return str;
}

public static void main(String[] args){
ScopeTest test = new ScopeTest();
String tmp = test.getStr();
System.out.println(" getStr return : "+tmp);
System.runFinalization();
tmp = test.getStr();
System.out.println(" getStr return : "+tmp);
}
}

//
各位,运行的结果居然是打印出来 asdklajs;di ,不对啊,作为getStr()的局部变量str它的生存周期早过了,堆栈早就该关闭了啊。
我用c++运行类似的程序居然也能得到类似的结果。
为什么?
...全文
291 23 打赏 收藏 转发到动态 举报
写回复
用AI写文章
23 条回复
切换为时间正序
请发表友善的回复…
发表回复
swinging 2003-10-18
  • 打赏
  • 举报
回复
我保证,你在C++中找到的答案,在JAVA中即使勉强成立,也不是出现你这个问题的主要原因。根本在于,你都没理解JAVA回收内存的机制,它和C++完全不一样。最简单的,只要有一个引用指向一个对象,那么无论你作甚么都不可能让JAVA的垃圾收集器去把那个对象使用的内存收集掉,这和jvm是怎么调用函数一点关系也没有,更和堆啊栈啊搭不上边。
jkit 2003-10-16
  • 打赏
  • 举报
回复
晕,哪里是给我了啊,明明是全部给 goldenhua(深深地爱上了你)了。
wanderForEver 2003-10-15
  • 打赏
  • 举报
回复
结贴了。

不过你们没有提供了任何有用的信息,答案我是从c++里面找到的。

分全部给 jkit(郁闷之堕落的程序员) 了,不是因为他给了我答案,而是他说的离答案最近。
KillAllError 2003-10-08
  • 打赏
  • 举报
回复
package test;

public class ScopeTest{

public String getStr(){
String str = new String("asdklajs;di");
return str;
}

public static void main(String[] args){
ScopeTest test = new ScopeTest();
String tmp = test.getStr();
System.out.println(" getStr return : "+tmp);
System.runFinalization();
tmp = test.getStr();
System.out.println(" getStr return : "+tmp);
}
}

好像你在做無用功呀!
getStr裏面
String str = new String("asdklajs;di");
每次調用這個方法Str都被賦給了一個新的引用!
System.runFinalization();根本對你的結果不會有影響。
首先不談垃圾收集是怎麽收集的,你每次都給str一個新的對象,Java要回收也只是會收上一個對象的並不是回收str。就算是回收str,你調用String str 又重新定義了這個變量,所以根本就不能證明什麽!
vampire1129 2003-10-08
  • 打赏
  • 举报
回复
RangeTest 的构造函数在哪
TEM从GETSTR()中得到字符串,他又没被消除当然还在
wanderForEver 2003-10-08
  • 打赏
  • 举报
回复
各位大哥,我都不想说什么好了。于是我把 getStr()改成

public String getStr(){
String str = new String("adfalkjjfa");
return str+"123";
}

结果还是一样。

package test;

public class ScopeTest{

public StringBuffer getStr(){
StringBuffer buf = new StringBuffer("asdmonster");
return buf;
}

public static void main(String[] args){
ScopeTest test = new ScopeTest();
StringBuffer tmp = test.getStr();
System.out.println(" getStr return : "+tmp);
}
}

结果还是一样。


dyf2001 2003-10-08
  • 打赏
  • 举报
回复
垃圾问题,怎么想的?
jkit 2003-10-08
  • 打赏
  • 举报
回复
首先:对象是放在堆里的,对象的引用才是放在栈里的。
public String getStr(){
String str = new String("adfalkjjfa");
return str;
}
该方法中,对象"adfalkjjfa"放在堆里,它的引用str放在栈里。
该方法退出时,栈里的str被释放,对象"adfalkjjfa"依然在堆里。但是由于该方法有返回值,return str;所以将str的值拷贝一份返回(值传递,该值是对象"adfalkjjfa"在堆里的地址)。所以该方法并不是返回了局部变量(它的生命周期已过),而是返回了该局部变量的一份拷贝,依然是指向对象"adfalkjjfa"的一个引用。
wanderForEver 2003-10-08
  • 打赏
  • 举报
回复
期待更多精彩的回答。
wanderForEver 2003-10-08
  • 打赏
  • 举报
回复
综合大家的讨论,我的想法是:

大家有没有想过函数的调用jvm是怎么一个调用过程?
不知道除了使用堆栈,还有没有别的方式——好像是没有。

当栈顶的数据被弹出以后,如果被弹出的数据地址不被清空应该说是jvm设计上的一个bug不是吗?
casemy 2003-10-08
  • 打赏
  • 举报
回复
我明白搂住的意思,str确实已经不存在了
但是在调用方法时有这么一个过程,产生str,对str赋值,然后str把值赋给temp
,这个时候方法调用结束,而str也就不存在了,之后和str也就没有关系了

至于第二个例子,由于楼主用了同样的变量名,容易混淆,其实这时候两个str是不一样的
alienbat 2003-10-08
  • 打赏
  • 举报
回复
不是非常正常吗?我看不出有什么不对。
System.runFinalization();
垃圾回收只会回收没有任何引用的对象,tmp仍有引用,当然存在。要是没有引用你怎能print出来?
再者,System.runFinalization()只是建议垃圾回收工作,而不是强迫垃圾回收工作。java的垃圾回收机制是不能被控制的。

你在钻牛角尖。
jkit 2003-10-08
  • 打赏
  • 举报
回复
楼主,你觉得
public String getStr(){
String str = new String("adfalkjjfa");
return str;
}

public String getStr(){
String str = new String("adfalkjjfa");
return str+"123";
}
这两个方法有区别吗?
他们都等价于:
public String getStr(){
return <java.lang.String>;
}
看来是没有认真看我上面的回复哎~
swinging 2003-10-07
  • 打赏
  • 举报
回复
你的思路有问题,
请问你用的JAVA还是C++?

不如描述你要解决的问题,看大家能不能帮你吧。

在JAVA中,只要存在引用,对象不会被作为垃圾收集掉的。
wanderForEver 2003-10-07
  • 打赏
  • 举报
回复

那这个程序该怎么写————体现出堆栈的关闭。

我的理解是无论tmp还是str,都是对一个内存地址的引用,当相应的堆栈关闭以后,应该内存被回收的。
sunnyshine 2003-10-07
  • 打赏
  • 举报
回复
运行System.runFinalization();后
是关闭了rangeTest1这个对象吧!
str仍然有值啊!
sunnyshine 2003-10-07
  • 打赏
  • 举报
回复
你不是返回了str吗?
String tmp = test.getStr();相当于 tmp = str;
当然会输出asdklajs;di了!
wanderForEver 2003-10-07
  • 打赏
  • 举报
回复
package test;

/**
* <p>Title: </p>
* <p>Description: </p>
* <p>Copyright: Copyright (c) 2003</p>
* <p>Company: </p>
* @author unascribed
* @version 1.0
*/

public class RangeTest {

public RangeTest() {}

public String getStr(){
String str = new String("adfalkjjfa");
return str;
}


public static void main(String[] args) {
try {
RangeTest rangeTest1 = new RangeTest();
String str = rangeTest1.getStr();
System.runFinalization();
str = rangeTest1.getStr();
rangeTest1.finalize();
// rangeTest1 = null;
System.out.println(" getStr is : "+str);
}
catch (Throwable ex) {
ex.printStackTrace();
}
}
}
//都不行,天啦,没有天理啊。
storm999 2003-10-07
  • 打赏
  • 举报
回复
看不懂.不這樣那是怎樣?
goldenhua 2003-10-07
  • 打赏
  • 举报
回复
不要把对象和引用混淆起来!
对象只能通过引用来使用,只有无法通过任何路径访问到的对象才被垃圾收集!
譬如:
Java中单链表的释放非常简单,只要把表头引用赋值为null即可:

head = null;
这样后续节点不管有多少,由于没有任何办法访问到,都会被垃圾收集。(不过我试了一下,当链表长度超过一定大小时,sun的JVM似乎就很难成功的垃圾收集之,这与垃圾收集机制有关系)
加载更多回复(3)

62,614

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧