前言
大家都知道,对于基本类型(int char float等等),java是传值。对于某个对象,java传递的是什么呢?
疑惑
最近刷 leetcode 删除链表一个节点的时候, 遇到这个问题
看下面代码
public class DeleteNodeLinkedList {
public static void main(String[] args) {
ListNode n0 = new ListNode(10);
ListNode n1 = new ListNode(11);
ListNode n2 = new ListNode(12);
ListNode n3 = new ListNode(13);
n0.next = n1;
n1.next = n2;
n2.next = n3;
System.out.println("before delete in main " + n2);
deleteNode(n2);
System.out.println("after delete in main " + n2);
}
public static void deleteNode(ListNode node) {
if (node == null) {
return;
}
// the last node
if (node.next == null) {
node = null;
}
System.out.println("before assignment in deleteNode " + node);
node = node.next; //这行代码影响很大
System.out.println("after assignment in deleteNode " + node);
}
}
class ListNode {
int val;
ListNode next;
ListNode(int x) {
val = x;
}
}
在方法体
deleteNode(ListNode node)
我们用node = node.next;
改变了node, 企图删除这个node
输出结果
before delete in main ListNode@27feae0f
before assignment in deleteNode ListNode@27feae0f
after assignment in deleteNode ListNode@41556f4c
after delete in main ListNode@27feae0f
令人遗憾的是, 从方法体内的
before assignment
和before assignment
可以看出, 在方法体内部, node 是改变了但是在mian函数里面, node 的值
before delete
和after delete
是一样的
总结与反思
Note
java 是传值的,
对于对象类型,在方法体内部, 也是传递了一个引用的副本
这其实也不难理解, 比如说
isSameTree(r0, r0)
我将一个对象作为a参数和b参数传进去, 如果都是同一个引用, 不是混乱了.所以在方法体的内部是引用的副本,上文
node = node.next;
是引用的副本改变了,但是真实的引用被没有改变。所以方法里的改变并没有作用到main函数中。
当被传递给函数之后,一个对象至少存在两个引用
我们可以通过引用的副本改变这个实力的成员变量,但是改变这个实例本身只在方法内部起作用。
看下面这个例子
public class DeleteNodeLinkedList {
public static void main(String[] args) {
ListNode n0 = new ListNode(10);
ListNode n1 = new ListNode(11);
ListNode n2 = new ListNode(12);
ListNode n3 = new ListNode(13);
n0.next = n1;
n1.next = n2;
n2.next = n3;
System.out.println("val before delete in main " + n2.val);
deleteNode(n2);
System.out.println("val after delete in main " + n2.val);
}
public static void deleteNode(ListNode node) {
if (node == null) {
return;
}
// the last node
if (node.next == null) {
node = null;
}
System.out.println("val before assignment in deleteNode " + node.val);
node.val = node.next.val; //注意这行代码
System.out.println("val after assignment in deleteNode " + node.val);
}
}
class ListNode {
int val;
ListNode next;
ListNode(int x) {
val = x;
}
}
这个我们在方法体内部改变的是对象成员变量的值, 发现是成功的
改变成员变量 输出
val before delete in main 12
val before assignment in deleteNode 12
val after assignment in deleteNode 13
val after delete in main 13