今天小伙伴问我一段代码:
public static ListNode create(int[] array) {
if (array == null || array.length == 0)
return null;
ListNode head = new ListNode(0);
ListNode node = head;
for (int i = 0; i < array.length; i++) {
ListNode temp = new ListNode(array[i]);
node.next = temp;
node = temp;
System.out.println(node.val);
}
return head.next;
}
为什么在方法内head指向的是链表的最后一个结点,但是在main方法中head指向的是第一个结点。
我进行了测试
public class Main {
public static class ListNode{
int val;
ListNode next; //下一个链表对象
ListNode(int x){val=x;} //赋给结点的值
}
public static ListNode create(int[] array) {
if (array == null || array.length == 0)
return null;
ListNode head = new ListNode(0); //预指针,其下一个结点指向真正的头结点
ListNode node = head;
for (int i = 0; i < array.length; i++) {
ListNode temp = new ListNode(array[i]);
node.next = temp;
node = temp;
System.out.println(node.val);
}
return head.next;
}
public static void main(String[] args)
{
int[] array={1,2,3,4,5,6,7,8,9};
ListNode a=create(array);
System.out.println("---------"+a.val);
}
}
发现真的是a.val输出为1。
后来经过一波讨论,查阅了很多资料得出一下结论。
这是因为ListNode a=create(array);被初始化,将head.next的初值1赋值给了a。然后再执行create方法。但由于java的引用传递,虽然方法内head的最后的值变为9,但是最后赋值给a的值依然为其初始值1。
值传递:
在方法被调用时,实参通过形参把它的内容副本传入方法内部,此时形参接收到的内容是实参值的一个拷贝,因此在方法内对形参的任何操作,都仅仅是对这个副本的操作,不影响原始值的内容。
引用传递:
引用也就是指向真实内容的地址值,在方法调用时,实参的地址通过方法调用被传递给相应的形参,在方法体内,形参和实参指向内存地址,对形参的操作会影响的真实值。
JVM内存模型中,方法是存在虚拟栈中的,一个线程独享一个栈,而堆和方法区是所有线程共享的。JAVA的引用传进函数时 , 会复制一个引用与实参指向同一对象的引用, 操作的不是同一个引用。如下图所示:
总的来说就是只有当变量本身的值发生改变,值才会改变。