一、Java到底是值传递还是引用传递
这个话题一直颇具争议,那我也谈一下自己的见解吧…
二、什么是值传递和引用传递
搜罗了一下网上的说法:
- 值传递:指的是在方法调用时,传递的参数是按值的拷贝传递,这样在函数中如果对参数进行修改,将不会影响到实际参数。
- 引用传递:方法调用时,实际参数与形式参数指向同一个地址,在方法执行中,对形式参数的操作实际是就是对实际参数的操作
三、基本数据类型的参数传递方式
这个应该无异议:值传递
四、引用类型的参数传递方式
1.引入
当java方法中传递的是引用数据类型时,参数的传递方式为址传递,传递的是引用数据的地址的复制
示例代码:
public class MyTest {
public static void main(String args[]) {
User user1 = new User();
User user2 = new User();
System.out.println(user1);
System.out.println(user2);
System.out.println("");
swap(user1, user2);
System.out.println("");
System.out.println(user1);
System.out.println(user2);
}
private static void swap(Object obj1, Object obj2){
Object obj3 = obj1;
obj1 = obj2;
obj2 = obj3;
System.out.println(obj1);
System.out.println(obj2);
}
}
结果:
com.fzz.test.User@677327b6
com.fzz.test.User@14ae5a5
com.fzz.test.User@14ae5a5
com.fzz.test.User@677327b6
com.fzz.test.User@677327b6
com.fzz.test.User@14ae5a5
分析:
可以看到,在方法中交换两个对象的值,不会影响原来的对象,传递的参数的地址已经交换,但原来的对象的地址还是没变,可以说明,Java中引用数据类型传递的是地址的拷贝
2.总结
- 当传递的拷贝地址没有指向新的地址的时候,这时候修改该地址指向内存空间的值,那么原来的值也会改变。
- 当传递的拷贝地址指向了新的地址的时候,此时修改该地址指向内存空间的值,则不会影响原来的值。
下面这个例子,就是改变了拷贝地址:
public class Test {
public static void main(String[] args) {
String str = "String";
change(str);
System.out.println(str);
}
private static void change(String str){
str = "new String";
System.out.println(str);
}
}
输出:
new String
String
分析:
因为String是字符数组,为不可变类型,每一次重新赋不同的值,会重新开辟内存空间,即拷贝地址的值已经变为了新的地址值,但是原来的地址所指向内存空间里的值依然存在。
五、到底传什么类型不重要
- 从引用类型参数传递的方式来看,它偏向于值传递,因为它是地址值的拷贝。
- 从引用类型参数传递的内容来看,它确实是传的引用地址,当指向的地址不改变的时候,它内存中值的改变会影响原来的值,无疑偏向了引用传递。
- 我认为,只要理解了其中的传递原理就好了,到底是什么传递方式就见仁见智了。