关于Java的值传递我们知道:Java中基本类型作为函数参数传递就是值传递,无论在函数中对传进去的值做什么操作,函数外面声明的变量值都不会有什么改变,而对象作为函数参数传递进去则不然,为什么说不然呢,请看下面的代码。
下面的代码中有三个函数,一个值传递,两个引用传递
package com.learn;
public class main {
public static void change(int data){//值传递
data = data+1;
}
public static void changeref(StringBuffer data){//引用传递1
data = new StringBuffer("in changeref");
}
public static void changeref_2(StringBuffer data){//应用传递2
data.append(" now changed");
}
public static void main(String[] args){
int num = 10;
System.out.println("num before changed: "+num);
change(num);
System.out.println("num after changed: "+num);
StringBuffer str = new StringBuffer("outside");
System.out.println("str before changed: "+str);
changeref(str);
System.out.println("str after changed: "+str);
StringBuffer str_2 = new StringBuffer("outside");
System.out.println("str_2 before changed: "+str_2);
changeref_2(str_2);
System.out.println("str_2 after changed: "+str_2);
}
}
复制代码
num before changed: 10
num after changed: 10
str before changed: outside
str after changed: outside
str_2 before changed: outside
str_2 after changed: outside now changed
Process finished with exit code 0
复制代码
从代码的运行结果可以看到,不出意料的,我们可以看到基本类型int的值在经过函数操作后没有任何变化,而同样是引用传递str与str_2的结果却完全不同,这是为什么呢?
回到代码,可以发现,changeref()函数中data直接指向了一个新的StringBuffer对象,经过此操作后函数外的str值并没有任何改变,而changere_2()函数中data是往后追加了一段字符串,此操作后函数外的str_2值改变了。这是为什么呢?
在讨论这个问题之前,先来讨论一下什么是值传递,什么是引用。首先值传递的概念是将值复制一份传入函数。而引用的概念就涉及到了jvm存储模型,在jvm存储模型中,基本类型都是直接存在Java虚拟栈中的,而对象都是新建在堆区,要想访问位于堆区的对象,需要在Java虚拟栈中建立一个变量,它的值是:指向某个对象的地址,这个变量就是引用。
而在Java中并没有真正的引用传递,通常所说的引用传递其实也是值传递。而在上面的代码中,changeref()直接改变data的值是对复制过来的引用值进行改变,changeref_2()是对data指向的对象进行操作,换言之就是对堆中的对象进行改变,所以就出现这样的结果。