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();
    }
  }
}
//都不行,天啦,没有天理啊。

解决方案 »

  1.   

    你不是返回了str吗?
    String tmp = test.getStr();相当于 tmp = str;
    当然会输出asdklajs;di了!
      

  2.   

    运行System.runFinalization();后
    是关闭了rangeTest1这个对象吧!
    str仍然有值啊!
      

  3.   


    那这个程序该怎么写————体现出堆栈的关闭。我的理解是无论tmp还是str,都是对一个内存地址的引用,当相应的堆栈关闭以后,应该内存被回收的。
      

  4.   

    你的思路有问题,
    请问你用的JAVA还是C++?不如描述你要解决的问题,看大家能不能帮你吧。在JAVA中,只要存在引用,对象不会被作为垃圾收集掉的。
      

  5.   

    无论是java还是c++.函数的调用过程都是方法开始的时候进栈,退出的时候出栈。栈顶的数据将被弹出。
    也就是说,无论java还是c++,我的getStr()都不应该返回能够预料到的结果。
    我想这是一个关系到变量生命周期的问题,每个人都会被问到过若干回。回答无一例外的是getStr()的返回值不值得信赖——我记得林锐写的那本书上就是这么说的。但是事实结果并不是这样。
      

  6.   

    System.runFinalization();
    这个是干什么用呢?
      

  7.   

    不要把对象和引用混淆起来!
    对象只能通过引用来使用,只有无法通过任何路径访问到的对象才被垃圾收集!
    譬如:
       Java中单链表的释放非常简单,只要把表头引用赋值为null即可:      head = null;
       这样后续节点不管有多少,由于没有任何办法访问到,都会被垃圾收集。(不过我试了一下,当链表长度超过一定大小时,sun的JVM似乎就很难成功的垃圾收集之,这与垃圾收集机制有关系)
      

  8.   

    综合大家的讨论,我的想法是:大家有没有想过函数的调用jvm是怎么一个调用过程?
    不知道除了使用堆栈,还有没有别的方式——好像是没有。当栈顶的数据被弹出以后,如果被弹出的数据地址不被清空应该说是jvm设计上的一个bug不是吗?
      

  9.   

    首先:对象是放在堆里的,对象的引用才是放在栈里的。
    public String getStr(){
        String str = new String("adfalkjjfa");
        return str;
    }
    该方法中,对象"adfalkjjfa"放在堆里,它的引用str放在栈里。
    该方法退出时,栈里的str被释放,对象"adfalkjjfa"依然在堆里。但是由于该方法有返回值,return str;所以将str的值拷贝一份返回(值传递,该值是对象"adfalkjjfa"在堆里的地址)。所以该方法并不是返回了局部变量(它的生命周期已过),而是返回了该局部变量的一份拷贝,依然是指向对象"adfalkjjfa"的一个引用。
      

  10.   

    各位大哥,我都不想说什么好了。于是我把 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);
      }
    }结果还是一样。
      

  11.   

    RangeTest 的构造函数在哪
    TEM从GETSTR()中得到字符串,他又没被消除当然还在
      

  12.   

    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 又重新定義了這個變量,所以根本就不能證明什麽!
      

  13.   

    楼主,你觉得
    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>;
    }
    看来是没有认真看我上面的回复哎~
      

  14.   

    不是非常正常吗?我看不出有什么不对。
    System.runFinalization();
    垃圾回收只会回收没有任何引用的对象,tmp仍有引用,当然存在。要是没有引用你怎能print出来?
    再者,System.runFinalization()只是建议垃圾回收工作,而不是强迫垃圾回收工作。java的垃圾回收机制是不能被控制的。你在钻牛角尖。
      

  15.   

    我明白搂住的意思,str确实已经不存在了
    但是在调用方法时有这么一个过程,产生str,对str赋值,然后str把值赋给temp
    ,这个时候方法调用结束,而str也就不存在了,之后和str也就没有关系了至于第二个例子,由于楼主用了同样的变量名,容易混淆,其实这时候两个str是不一样的
      

  16.   

    结贴了。不过你们没有提供了任何有用的信息,答案我是从c++里面找到的。分全部给  jkit(郁闷之堕落的程序员)  了,不是因为他给了我答案,而是他说的离答案最近。
      

  17.   

    晕,哪里是给我了啊,明明是全部给 goldenhua(深深地爱上了你)了。
      

  18.   

    我保证,你在C++中找到的答案,在JAVA中即使勉强成立,也不是出现你这个问题的主要原因。根本在于,你都没理解JAVA回收内存的机制,它和C++完全不一样。最简单的,只要有一个引用指向一个对象,那么无论你作甚么都不可能让JAVA的垃圾收集器去把那个对象使用的内存收集掉,这和jvm是怎么调用函数一点关系也没有,更和堆啊栈啊搭不上边。