关于值传递和引用传递的一个典型例子

深入理解引用传递

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地址。

你可能感兴趣的:(Java学习笔记)