先看一个值传递案例
@Test
public void fun1(){
String name = "name1";
fun2(name);
System.out.println(name);
}
public void fun2(String name){
name = "name2";
}
粗看代码,快速通读下来,name变量被传递给fun2方法,值应该被修改为 “name2”,然后fun1方法中应该打印出 “name2” 才对… 但是打印的是 name1
回头细想,原因很简单,因为在java中参数传递分为值传递和引用传递,说白了fun2(name)传递给fun2方法,本质等价于 fun2(“name1”),将值本身传递了过去,所以fun2方法中的name仅仅是该方法的一个局部变量,跟fun1中的name变量毫无关系。
那么java中哪些是值传递哪些是引用传递呢?
基本类型包括:byte,short,int,long,char,float,double,Boolean,returnAddress
引用类型包括:类类型,接口类型和数组。
需要注意特殊类型 String Integer Double 等几个基本类型的包装类,他们都是immutable类型,他们也是值传递
然后再看一个引用传递案例
@Test
public void fun1(){
StringBuffer sb1 = new StringBuffer("name1");
fun2(sb1);
System.out.println(sb1);
}
public void fun2(StringBuffer sb){
StringBuffer sb2 = new StringBuffer("name2");
sb = sb2;
}
现在的StringBuffer对象是妥妥的引用对象,传递的也是引用,而非值本身,所以打印出来应该是 “name2”
呵呵… 打印结果是 “name1”
What FK? Are you kidding me ?
回头再捋捋思路,sb1传递给fun2方法,这里肯定是引用传递,不用怀疑!!!
那细看发现,问题只有发生在 sb = sb2 语句了,sb2把自己的引用值赋值给了sb,在fun2方法中,sb对象确实是指向了sb2所在的堆地址,且值为"name2",那为什么回到fun1方法中,sb1的值还是"name1"呢?
我们抽象理解~~
案例2和案例1本质是一样的,什么所谓的值传递和引用传递,本质我们都可以理解为值传递
只不过案例1中传递的值是 “值本身’name1’(有点绕~~)”,案例2中传递的值是一个引用值,是栈中的一个值, 比如 “StringBuffer@254”,不管是案例1中的"name1" 还是案例2中的 “StringBuffer@254”,它们都是一个局部变量,都在fun1中才有效(局部变量的作用域决定的),所以不能在fun2中修改一个另一个方法中的局部变量
也就是案例1中的fun2方法 传递的参数"name1" 跟 fun1 中的变量 name 没有关系
同理:案例2中的fun2方法 传递的参数"StringBuffer@254" 跟 fun1 中的变量 sb1 没有关系
唯一的区别是一个是真实值,一个是栈中的引用值
如果想要修改引用中的值需要修改引用指向堆中的值,代码如下:
@Test
public void fun1(){
StringBuffer sb1 = new StringBuffer("name1");
fun2(sb1);
System.out.println(sb1);
}
public void fun2(StringBuffer sb){
sb.delete(0, sb.toString().length());
sb.append("name2");
}