今天写红黑树的时候碰到个基础问题,涉及到引用对象,形参,内存空间和内存地址几个知识点
情景还原
节点类
class Node{
private int val;
}
以demo方法为入口
先分别实例化了两个Node类
并分别给其val变量(int类型)赋值为1和2
将node1和node2传递给demo2()方法
在demo2()方法里面将node2赋值给node1
最后打印node1.val
public class RBTree {
@Test
public void demo() {
Node node1 = new Node();
node1.val = 1;
Node node2 = new Node();
node2.val = 2;
demo2(node1, node2);
System.out.println(node1.val);
}
public void demo2(Node preNode, Node sufNode) {
preNode = sufNode;
}
}
但这里出现了问题,最后打印出来node1.val的值为1,第一反应是赋值失败
然后我又尝试修改demo2()的方法,将node2.val赋值给node1.val
public void demo2(Node preNode, Node sufNode) {
preNode.val = sufNode.val;
}
重跑一次,打印出来的值为2,说明赋值成功
问题分析
第一次运行
实例化node1和node2对象的时候分别会在内存中开辟出两块内存空间
每一块内存空间都是有地址的,称为内存地址
所以这时node1和node2分别指向node1和node2的内存地址,node1和node2本身并不存储数据,只存放内存地址,所以称为引用对象
(每次使用node1或node2对象时,都是先通过指针获取到内存地址,然后再去内存中找到对应的内存空间,再进行操作的)
调用demo2()方法时将node1对象和node2对象作为参数传入
此时preNode指向node1的内存地址,sufNode指向node2的内存地址
preNode和sufNode都是方法中的形参,生命周期只存在于当前方法体中,并不能代表node1或node2本身
所以当我把sufNode赋值给preNode时,只是把preNode的指针指向了sufNode,这时node1的指针还是没有发生任何改变
所以当我进行打印的时候node1.val的值还是为1
第二次运行
为什么直接把sufNode.val赋值给preNode.val就可以成功?
上面说过preNode和sufNode都只存储内存地址,node1和node2也是存储内存地址,preNode和node1指向同一个内存空间,sufNode和node2指向同一内存空间。
sufNode.val赋值给preNode.val是从sufNode.val的内存空间取出对应值,并直接修改preNode.val对应的内存空间,直接操作了内存空间,当node1获取val时就会发现值已经变为了2
1)未做赋值操作时
2)将sufNode赋值给preNode后
3)将sufNode.val赋值给preNode.val后