以下程序输出什么内容:
public class Test1 {
public void test1(){
StringBuilder sb1 = new StringBuilder("a");
StringBuilder sb2 = new StringBuilder("b");
int a = 1;
test2(a, sb1, sb2);
System.out.println(“a=”+a);
System.out.println(“sb1=”+sb1);
}
public void test2(int a,StringBuilder sb1,StringBuilder sb2){
a = 100;
sb1.append("b");
sb1 = sb2;
}
public static void main(String[] args) {
Test1 t = new Test1();
t.test1();
}
}
输出:a=1
sb1=ab
根据结果可以知道a并没有改变,sb1只是通过append改变了内容,对于sb1=sb2并不会对“真正的”sb1进行操作,所以没有发生改变。
那么,这是为什么呢?
首先,看看这三句话:对于Java传值,
- 1.对象传引用;
- 2.基本数据类型传值;
- 3.String虽然是引用数据类型,由于创建后不能修改,可以认为是传值。
接着,具体解释这几句话:
- 1.将一个对象作为参数传到一个函数中,其实是将这个对象的内存地址传过去了,即形参指向该内存地址,对于题中的sb1以下会解释。
- 2.将一个基本数据类型传到一个函数中,其实是将这个基本数据类型的值的一个副本穿过去了,所以修改副本的值并不会对本来的实参有影响,这个比较好理解,题中的a就不解释了。
最后,对那道题进行解释:
一张图就可以很清楚的搞定
一开始,实参sb1、sb2各自指向堆中的内存地址(黑线),将sb1,sb2作为形参传入test2()函数后,在栈中的形参各自指向对应的内存地址(蓝线)
当执行
- sb1.append(“b”);
由于现在sb1(形参)仍然指向堆中的“a”,所以会变成“ab”;
但是当执行
- sb1 = sb2;
sb1(形参)就改变了指向的内存地址,变成了指向堆中的“b”(红线),但是注意,
- System.out.println(“sb1=”+sb1);
这句话是输出sb1(实参),而现在sb1(实参)指向的堆中的内容,现在是“ab”,所以,最后输出结果是ab。