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
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) 堆栈(Stack):位于常规RAM(随机访问存储器)区域,但可通过它的“堆栈指针”获得处理器的直接支持。堆栈指针若向下移,会创建新的内存;若向上移,则会释放那些内存。这是一种特别快、特别有效的数据保存方式,仅次于CPU的寄存器。创建程序时,Java编译器必须准确地知道堆栈内保存的所有数据的“长度”以及“存在时间”。这是由于它必须生成相应的代码,以便向上和向下移动指针。这一限制无疑影响了程序的灵活性,所以尽管有些Java数据要保存在堆栈里——特别是对象的引用(也可称为对象的引用变量),但Java中的对象不会放在其中。
(2) 堆(Heap)。一种常规用途的内存池(也在RAM区域),其中保存了Java对象。和堆栈不同,“内存堆”或“堆”(Heap)最吸引人的地方在于编译器不必知道要从堆里分配多少存储空间,也不必知道存储的数据要在堆里停留多长的时间。因此,用堆保存数据时会得到更大的灵活性。要求创建一个对象时,只需用new命令编制相关的代码即可。执行这些代码时,会在堆里自动进行数据的保存。当然,为达到这种灵活性,必然会付出一定的代价:在堆里分配存储空间时会花掉更长的时间!这是导致Java性能不佳的因素之一。
参考<practical java>实践1 参数以by value方式而非by reference方式传递这里的区别在于 String是用来表示那些建立以后就不再改变的字符序列,即对象是只读且不可变的.StringBuffer用来表示内容可变的字符序列,提供一些函数用来修改底部的字符序列的内容.也就是说当改变String的时候,String实际上重新生成新的String对象,然后将现在的引用指向新的String对象.请参考 <practical java>实践63 immutable classes(不可变类)
可以用c++的观点来理解一下。
写入下的函数(c/c++)
void chage(int *b,int *c)//对于这两个来说,都是传的值.
{
int mm=0;
b=&mm;//这就相当于string,因为b就是原来调用的值的一个拷贝,
//你改变了它又有何用?
*c=5;//这就相相当于stringbuffer直接操作了它所指的对象。
}
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);
}
}
sb.append("aaaa"); 不会分配空间,而在是原字符串上将值改为"aaaa"
首先,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章