第一步: method(s); 经过了这一步,行参所引用的对象就是实参所引用的对象,也就是实参和行参引用到了同一个字符串对象,那个对象的内容是:"Hello";然后 s+="world"; 注意,这一句完全等价于: s = s + "world"; 问题就出在 s + "world"; 上,这个表达式并不改变s本身,而是将s的内容和“world”链接起来,形成一个新的字符串对象,然后这个新的字符串对象的引用又反过来赋给了s——于是,s从现在开始引用到了一个新的字符串对象,它原来在参数传递过程中所引用的那个对象已经不再归它引用了。换句话说,从现在开始,它和实参不在引用同一个对象。函数返回后,行参作为一个引用不再有效。但实参却一直没有被改变过。
method(s);
经过了这一步,行参所引用的对象就是实参所引用的对象,也就是实参和行参引用到了同一个字符串对象,那个对象的内容是:"Hello";然后
s+="world";
注意,这一句完全等价于:
s = s + "world";
问题就出在
s + "world";
上,这个表达式并不改变s本身,而是将s的内容和“world”链接起来,形成一个新的字符串对象,然后这个新的字符串对象的引用又反过来赋给了s——于是,s从现在开始引用到了一个新的字符串对象,它原来在参数传递过程中所引用的那个对象已经不再归它引用了。换句话说,从现在开始,它和实参不在引用同一个对象。函数返回后,行参作为一个引用不再有效。但实参却一直没有被改变过。
仔细研究一下String类的所有方法,你会发现,没有一个方法是会改变对象本身的。包括replace,substring等方法,也都是通过返回值返回处理后的新对象而已,老的对象从来不变。
Java里头除了内建类型,其他都是传引用,而这里关键的问题是:
s + "world";
改变的是引用本身而不是引用所引用的对象。
{
s+="world";
}
执行method方法的时候,虽然传递了一个字符串变量s,但是,s+="world";实际上又在内存中产生了一个新的对象,这个新的对象是Helloworld,当method方法调用结束后,method的生命周期结束了,在堆当中的“Helloworld”字符串变量变成了孤儿,不再被任何引用变量所引用。
但是,在main方法中的产生的Hello变量仍然存在,并为main方法中的s所引用。所以在main方法中执行System.out.println(s);的时候,输出的结果仍然是原来的Hello
class Test
{
public static void main(String[] args)
{
String s=new String("Hello");
ss=method(s);
System.out.println(ss);
}
public static void method(String s)
{
s+="world";
return s;
}
}