在做剑指Offer的时候,在做二叉树的镜像这道题的时候让我遇到了值传递和引用传递的困惑,如下所示:
public class Solution {
public void Mirror(TreeNode root) {
if (root == null)
return;
TreeNode temp = root.left;
root.left = root.right;
root.right = temp;
//swap(root.left, root.right);
Mirror(root.left);
Mirror(root.right);
}
void swap(TreeNode left, TreeNode right) {
TreeNode temp = left;
left = right;
right = temp;
}
}
上面的代码可以通过测试用例,但是,当我使用swap 函数而不是直接在Mirror中交换引用的值时,这时候就出现了问题。使用swap函数并没有让root的左右节点发生交换。接下来我们看看这到底是怎么回事?
首先说值传递,值传递是针对基本数据类型而言的,传递的是变量的一个副本,调用函数改变的只是副本的值,对原有变量没有任何影响;
public class Solution {
public void changeValue(int a) {
a = 0;
}
public static void mian (String []args) {
Solution s = new Solution();
int a = 1;
s.changeValue(a);
System.out.println(a); //a = 1
}
}
函数改变的是副本的值,对原值不做改变
对于引用传递,引用传递是针对对象而言的,传递的是指向该对象的地址,调用函数改变的是该地址指向的对象,由于原地址和传递给函数的地址都指向同一个对象,所以引用传递实质上还是值传递,对地址进行拷贝,但指向的对象仍然还是那个对象。
public class Solution {
public void changeValue(TreeNode node) {
node.val = 0;
}
public static void mian (String []args) {
Solution s = new Solution();
TreeNode node = new TreeNode(1);
s.changeValue(node);
System.out.println(node.val); //node.val = 0;
}
}
可以看出,引用传递传递的是地址的拷贝,与原地址指向同一个对象,
但是,回到原来的问题,为什么swap()函数没能交换左右子数呢?因为swap()函数并不是改变引用所指向的对象,二是改变引用的指向,所以,swap 函数执行后,形参改变了指向,但是原来实参的值并没有发生改变,
从这里可以看出,java中所有的传递本质上都是值传递(传递副本)。