public class A {
  static void change(String s, StringBuffer sb) {
    s = "aaaa";  
    sb.setLength(0);
    sb.append("aaaa");
  }
  public static void main(String args[]) {
    String s = "bbbb";
    StringBuffer sb = new StringBuffer("bbbb");
    change(s, sb);
    System.out.println(s);
    System.out.println(sb);
  }
}怎么输出的bbbb,aaaa

解决方案 »

  1.   

    String不可变StringBuffer 可修改内容
      

  2.   

    而且你要了解Java传递参数引用的含义,和C++的方式是不一样的。
      

  3.   

    String 是值传递,StringBuffer 则是地址传递 所以
      

  4.   

    String的对象是放置在堆栈(Stack)中的StringBuffer 的对象是放置在堆(Heap)中的
    ========================================================================
    (1) 堆栈(Stack):位于常规RAM(随机访问存储器)区域,但可通过它的“堆栈指针”获得处理器的直接支持。堆栈指针若向下移,会创建新的内存;若向上移,则会释放那些内存。这是一种特别快、特别有效的数据保存方式,仅次于CPU的寄存器。创建程序时,Java编译器必须准确地知道堆栈内保存的所有数据的“长度”以及“存在时间”。这是由于它必须生成相应的代码,以便向上和向下移动指针。这一限制无疑影响了程序的灵活性,所以尽管有些Java数据要保存在堆栈里——特别是对象的引用(也可称为对象的引用变量),但Java中的对象不会放在其中。 
    (2) 堆(Heap)。一种常规用途的内存池(也在RAM区域),其中保存了Java对象。和堆栈不同,“内存堆”或“堆”(Heap)最吸引人的地方在于编译器不必知道要从堆里分配多少存储空间,也不必知道存储的数据要在堆里停留多长的时间。因此,用堆保存数据时会得到更大的灵活性。要求创建一个对象时,只需用new命令编制相关的代码即可。执行这些代码时,会在堆里自动进行数据的保存。当然,为达到这种灵活性,必然会付出一定的代价:在堆里分配存储空间时会花掉更长的时间!这是导致Java性能不佳的因素之一。 
      

  5.   

    java中只有值传递!!!StringBuffer传递的只是它的引用值!
    参考<practical java>实践1 参数以by value方式而非by reference方式传递这里的区别在于 String是用来表示那些建立以后就不再改变的字符序列,即对象是只读且不可变的.StringBuffer用来表示内容可变的字符序列,提供一些函数用来修改底部的字符序列的内容.也就是说当改变String的时候,String实际上重新生成新的String对象,然后将现在的引用指向新的String对象.请参考 <practical java>实践63 immutable classes(不可变类)
      

  6.   

    我同意楼上的java中只有值传递,因为传递的引用就是值传递。
    可以用c++的观点来理解一下。
    写入下的函数(c/c++)
                     void chage(int *b,int *c)//对于这两个来说,都是传的值.
                  {
                       int mm=0;
                        b=&mm;//这就相当于string,因为b就是原来调用的值的一个拷贝,
                               //你改变了它又有何用?
                        
                        *c=5;//这就相相当于stringbuffer直接操作了它所指的对象。
                                        }
      

  7.   

    调用change()方法时,两个参数都是进行引用值的传递.
    change()方法中,经参数传递,s指向了"bbbb"字符串,sb指向了"bbbb"字符串.
    执行s="aaaa"后,s指向了"aaaa"字符串,"bbbb"字符串仍由实参s引用指向,因为String类是常量类型.
    执行sb.append("aaaa")后,sb指向的字符串的值由"bbbb"改为"aaaa",因为StringBuffer类是可变类型.
    可以进行验证.在change()方法中将s打印出来
    public class A{
      static void change(String s, StringBuffer sb) {
        s = "aaaa";  
        sb.setLength(0);
        sb.append("aaaa");
        System.out.println(s);
      }
      public static void main(String args[]) {
        String s = "bbbb";
        StringBuffer sb = new StringBuffer("bbbb");
        change(s, sb);
        System.out.println(s);
        System.out.println(sb);
      }
    }
      

  8.   

    s="aaaa"; 会在堆内存中分配空间存放"aaaa",
    sb.append("aaaa"); 不会分配空间,而在是原字符串上将值改为"aaaa"
      

  9.   

    String是final类,你企图改变他的引用这是不可能的,StringBuffer也是final类,同样不能改变引用,但是值是可以改变的,你调用setLength(0),序列将被更改为一个新的字符序列,你再追加,所以
      

  10.   

    楼上的有点道理,不过string是在常量池中的
      

  11.   

    字符串池咯!呵呵String是一个极其特殊的类,而StringBuffer在这里可以理解为普通类传参数
      

  12.   

    看了那么多,我来说吧!
    首先,Java都是值传递
    这里当把s,sb(就是直string对象和stringbuffer对象)传递到方法中时!
    方法的形参分别拷贝了2 份 引用s 跟sb
    这时方法里的s跟mian里的s,方法里的sb跟main里的sb 都指向同一个对象!
    当修改方法里的sb的对象的值时候,因为方法里的sb与mian里的sb指向同一个对象,所以sb的值被改变了!而 方法s 这里创建了一个新的对象,此时方法里的s指向了另一个对象(“aaaa”),并不影响mian 里 s 所指的对象这里要注意的是 s跟 sb 一个是在原来的上修改对象的值,一个是创建一个对象!!(画下图对你们有帮助)
    还可以参考 core java2 第4章