全取决于replaceAll这个方法是怎么实现的。类似的,有这样一个例子:
//例6
1 void method1() {
2 StringBuffer x = new StringBuffer("Hello");
3 change1(x);
4 System.out.println(x);
5 }
6
7 void method2() {
8 StringBuffer x = new StringBuffer("Hello");
9 change2(x);
10 System.out.println(x);
11 }
12
13 void change1(StringBuffer sb) {
14 sb.append(" world!");
15 }
16
17 void change2(StringBuffer sb) {
18 sb = new StringBuffer("hi");
19 sb.append(" world!");
20 }
调用method1(),屏幕打印结果为:"Hello worl
d!"
调用method2(),我们认为结果应该是"hi world",因为sb传进来的是引用。可是实际执行的结果是"Hello"!
难道change2()又变成传值了?!其实change1()和change2()的确都是通过参数传入引用,但是在方法内部因为处理方法的不同而使结果大相径庭。我们还是从内存的角度分析:
执行method1()和change1()不用再多说了,上面的例子已经讲解过,这里我们分析一下method2()和change2()。
程序执行到第8行,x指向一个存放着"Hello"的内存空间。
变量x---->[存放值"Hello"]
第9行调用change2,将sb指向x指向的内存空间,也就是传入x的引用。
变量x \
-->[存放值"Hello"]
变量x /
到这里为止还没有什么异样,接下来执行18行,这里就出现了类似传入值拷贝的变化:new 方法并没有改变sb指向内存的内容,而是在内从中开辟了一块新的空间存放串"hi",同时sb指向了这块空间。
变量x---->[存放值"Hello"]
×原有的引用被切断
变量x---->[另一块存放"hi"的空间]
接下来再对sb进行append已经和x没有任何关系了。
所以,还有一条不成规则的规则:对于函数调用,最终效果是什么完全看函数内部的实现。比较标准的做法是如果会改变引用的内容,则使用void作为方法返回值,而不会改变引用内容的则在返回值中返回新的值。
虽然已经说了这么多,但是感觉传值还是传引用的问题依然没有完全说清楚。因为这个问题本身就是很难归纳总结的问题,所以更多的理解要靠平时的积累和形成。下面几个例子,给大家尝试进行分析。
//例7,打印结果是什么?
public static void main(String[] args) {
int a;
int b;
StringBuffer c;
StringBuffer d;
a = 0;
b = a;
c = new StringBuffer("This is c");
d = c;
a = 2;
c.append("!!");
System.out.println("a=" + a);
System.out.println("b=" + b);
System.out.println("c=" + c);
System.out.println("d=" + d);
}
//例8,打印结果是什么?
public class Test{
public static void main(String[] args) {
StringBuffer sb = new StringBuffer("Hello ");
System.out.println("Before change, sb = " + sb);
changeData(sb);
System.out.println("After changeData(n), sb = " + sb);
}
public static void changeData(StringBuffer strBuf) {
StringBuffer sb2 = new StringBuffer("Hi ");
strBuf = sb2;
sb2.append("World!");
}
}