深入理解引用传递
public class Main {
public static void changeStrBuffer(StringBuffer sb1, StringBuffer sb2) {
sb1.append(" World");
sb2 = sb1;
}
public static void main(String[] args) {
Integer a = 1;
Integer b = a;
b++;
System.out.println(a);
System.out.println(b);
System.out.println();
StringBuffer s1 = new StringBuffer("Hello");
StringBuffer s2 = new StringBuffer("Hello");
changeStrBuffer(s1, s2);
System.out.println(s1.toString());
System.out.println(s2.toString());
}
}
输出结果:
1
2
Hello World
Hello
Integer 是 int 基本数据类型的包装类,也是按地址传递的。但是由于 Integer 是不可变类,没有提供改变它值的方法。所以在上例中,执行完 b++
语句后创建了一个新值为2的 Integer 赋给 b ,此时 b 与 a 已经没有任何关系了。
对于第二对输出结果,要理解“引用也是按值传递的”。传递 s1 和 s2 的引用就是向方法中传递了两个地址值,在调用 append 方法时,修改了 sb1 所指向的字符串的值,但是 sb2 = sb1
语句只会修改 sb2 的值而对 s2 没有影响,因此 s2 的值前后保持不变。
下面补充 StringBuilder 的 append 方法和 String 的 + 的不同。
在上例中添加几行代码:
public class Main {
public static void changeStrBuffer(StringBuffer sb1, StringBuffer sb2) {
sb1.append(" World");
sb2 = sb1;
}
public static void changeStrBuffer(String sb1, String sb2) {
sb1 += " World";
sb2 = sb1;
}
public static void main(String[] args) {
StringBuffer s1 = new StringBuffer("Hello");
StringBuffer s2 = new StringBuffer("Hello");
System.out.println(s1.hashCode());
System.out.println(s2.hashCode());
changeStrBuffer(s1, s2);
System.out.println(s1.hashCode());
System.out.println(s2.hashCode());
s2.append("lalala");
System.out.println(s2.hashCode());
System.out.println();
String str1 = "Hello";
String str2 = "Hello";
System.out.println(str1.hashCode());
System.out.println(str2.hashCode());
changeStrBuffer(str1, str2);
System.out.println(str1.hashCode());
System.out.println(str2.hashCode());
str2 += "lalala";
System.out.println(str2.hashCode());
}
}
输出结果:
621009875
1265094477
621009875
1265094477
1265094477
69609650
69609650
69609650
69609650
1322399697
可以看出, append 方法不改变地址,在原引用后面直接添加。但是 + 会改变地址,指向的是常量池中的新的String地址。