标题起的很大,但是我只想讲一个比较容易令我困惑的问题。
今天在刷一道简单的链表题目时,又产生了困惑,这次结合之前的JVM知识希望把这个问题彻底解决。
先上代码
public static Node reverse(Node head){
if(head == null || head.next == null){
return head;
}
Node next = null;
Node pre = null;
while (head != null){
next = head.next;
head.next = pre;
pre = head;
head = next;
}
return pre;
}
代码很简单,就是一个反转链表,Node是一个普通的类。
首先我们知道,JVM中,声明的对象引用存储在栈中,它所代表的实际对象存储在堆中。
如
Node a = new Node();
a这个对象引用存储在栈中,JVM同时也在堆中开辟了一块真实的内存存储这个Node对象,
栈中存储的实际上是地址,这个地址指向堆中的内存
那么我上面的代码中
Node next = null;
Node pre = null;
把它们声明为null, 这时其实在堆中并没有开辟内存,但是在栈中,占用了栈的空间,只不过里面存储的是null 值。
同时在java里对象传递的时候,传递的都是引用(也就是对象的地址),这比传递整个对象高效的多。而基础类型,int,double等传递的才是值。
Node next = null;
Node pre = null;
while (head != null){
next = head.next;
head.next = pre;
pre = head;
head = next;
}
所以在这个循环中,一开始head.next被赋值为pre (也就是null)
紧接着 pre=head , pre在栈中原本是null,现在变成了一个地址,这个地址指向了堆中的head实际对象。而head.next并没有改变,在栈中暂时还是null。