java关于值传递还是引用传递的简单探讨

首先来看两个简单的小例子

eg1: 

​
 public static void main(String[] args) {
        StringBuffer sb = new StringBuffer("字符串");
        change(sb);
        System.out.println(sb);
    }

    public static void  change(StringBuffer sb){
        sb.append("++++++11111");
    }

​
    //结果:字符串++++++11111

eg2: 那下面这个只对change()方法进行了简单修改后,打印的值是多少呢?

  public static void main(String[] args) {
        StringBuffer sb = new StringBuffer("字符串");
        change(sb);
        System.out.println(sb);
    }

    public static void  change(StringBuffer sb){
        sb = new StringBuffer("新的字符串");
    }

    //结果:  字符串

问题:  为什么看起来没什么区别的方法,但是为什么打印sb,一个值看到了改变,一个却没有改变呢? 

我们都知道对象是 引用 类型, 也就是说 新建一个对象 这个sb 并不是对象本身, 而是对象的引用(可以理解为sb存着实际对象的地址值0x0000), 

java关于值传递还是引用传递的简单探讨

当我们调用方法change() 传入sb 的时候,实际上在内存中应该是这样的.

java关于值传递还是引用传递的简单探讨

所以当我们在change方法里对sb 进行 append("+++++111111")的时候, 修改的都是0x0000这个对象, 这是没什么疑问的.

所以第一个例子里打印出来的sb也的确发现sb改变了. 

 

重点:

但是为什么第二个方法里,打印sb 却还是 "字符串" ,不是如预料中的 "新的字符串" ?

java关于值传递还是引用传递的简单探讨

通过图可以发现,当我们在change()方法里 对传入的 变量 sb 进行赋值(new 新对象) 的操作的时候, 本来change()里的sb也是指向0x0000 但是由于进行了new操作, 这个时候 change方法的sb 就不指向 0x0000 而变为指向 0x1111 内容为 "新的字符串"  这个对象了, 但是在main()方法中打印的值依然是 sb (0x0000) 这个对象, 

 

那么我们改变一下方法,改成如下呢?

public static void main(String[] args) {
    StringBuffer sb1 = new StringBuffer("字符串1");
    StringBuffer sb2 = new StringBuffer("字符串2");
    change(sb1, sb2);
    System.out.println(sb1);
    System.out.println(sb2);
}

public static  void change(StringBuffer sb1,StringBuffer sb2){
    sb2 = sb1;
}

我们来分析一下:

java关于值传递还是引用传递的简单探讨

传入change方法里的sb1和sb2都只是实际对象地址的副本,

当我们在change()方法中 进行了   sb1 = sb2  操作的时候, 实际上是对sb1进行了赋值操作,改变了change()方法里sb1引用的实际对象,

java关于值传递还是引用传递的简单探讨

仔细看图,发现实际上只有 change()方法里的 sb1 引用的地址由 0x0000 改变成了 0x1111 指向了 "字符串2", 

但是main方法里打印的仍然是 main()里的 sb1和 sb2 , 实际上这两个变量引用的对象并没有变化.

所以打印结果 没有变化, change()方法并没有把sb2的内容赋给sb1 .

 

小结:

 当我们想调用一个方法,改变一个对象的内容的时候, 一定不要在方法内部对这个对象 进行 赋值 和 new 操作, 因为方法传入的对象实际上只是一个地址值, 进行赋值和new的时候改变了这个变量的地址值, 但是 方法外部的对象却无变化.