我一直在尝试在Java中实现LinkedList、Stack和Queue。
对于每个数据结构,我都使用了一个节点类。虽然我知道有更好的实现方法,但这不是我的问题重点,我只想关注我的问题。
public class Node<E> {
private E data;
private Node<E> next;
private Node<E> prev;
public Node(E data) {
this.data = data;
this.next = null;
this.prev = null;
}
public E getData() {
return this.data;
}
public Node<E> getNext() {
return this.next;
}
public Node<E> getPrev() {
return this.prev;
}
public void setPrev(Node<E> prev) {
this.prev = prev;
}
public void setData(E data) {
this.data = data;
}
public void setNext(Node<E> next) {
this.next = next;
}
}
现在有了node类,我对垃圾回收器的工作方式感到困惑,所以假设这是我的队列类
public class Queue<E> {
private int size;
private Node<E> head, tail;
public Queue() {
this.size = 0;
this.head = this.tail = null;
}
public Queue(E data) {
Node<E> temp = new Node<E>(data);
this.tail = this.head = temp;
this.size = 0;
}
public boolean enqueue(E data) {
Node<E> temp = new Node<E>(data);
if (this.head == null) {
this.tail = temp;
this.head = temp;
} else {
temp.setNext(this.head);
this.head.setPrev(temp);
this.head = temp;
}
this.size++;
return true;
}
public E dequeue() {
if (this.tail == null)
throw new IndexOutOfBoundsException();
else {
E data = this.tail.getData();
this.tail.setPrev(null);
this.tail = temp;
this.tail.setNext(null);
this.size--;
return data;
}
}
public int getSize() {
return this.size;
}
public E peak() {
if (this.tail == null)
throw new IndexOutOfBoundsException();
else
return this.tail.getData();
}
public boolean contains(E data) {
if (this.head == null)
return false;
else {
for (Node<E> cursor = this.head; cursor != null; cursor = cursor
.getNext()) {
if (cursor.getData().equals(data))
return true;
}
}
return false;
}
}
现在我有点混淆垃圾回收器的工作原理了。我听说,它会清理任何没有被指向的引用。所以我在我的出队类中一直得到空指针异常,在执行部分时。
this.tail.setNext(null);
现在,我听说垃圾回收器需要工作,没有任何引用它的东西,所以我想我的节点设置如下:
head tail
null<-[1]-><-[2]-><-[3]->null
每个节点都可以指向下一个节点和前一个节点,所以对于我的双端队列,我认为需要做一些事情:
1)获取数据(这很容易)
2)获取一个指向前一个节点的临时节点
Node<E> temp = this.tail.getPrev()
3) 现在我开始有些迷惑了,为了使每个节点不再被引用,我必须摆脱所有指向它的指针,这意味着我必须将其设置为 null。
this.tail.setPrev(null);
自从我删除节点之后,就无法向后退回去擦除该引用了。
head tail
null<-[1]-><-[2]-> null<-[3]->null
<-[temp]-> ( equals node [2])
4) 将尾部设置为指向临时节点temp,这是前一个节点所指向的节点
this.tail = temp;
不,应该是这样的
head tail
null<-[1]-><-[2]->(this still points to [3]) null<-[3]->null
5) 但第二个节点仍然指向 [3] 的内存地址,所以我继续执行。
this.tail.setNext(null);
为了使任何内容都不再引用我们的任何内存区域,需要进行以下操作:
head tail will be deleted by GC
null<-[1]-><-[2]->null null<-[3]->null
然而,在队列中只剩下一个节点时,NullPointerException
错误会出现在此部分。
现在,我知道我的做法可能有很多错误,因为我还在学习,但是我不确定我需要对每个节点做多少事情才能确保垃圾回收器将其清除,我需要将prev
和next
都设置为null
吗?还是只需要设置其中一个?请帮忙解决问题,谢谢;)
NullPointerException
是一个逻辑错误,而不是垃圾回收问题。垃圾收集器只清理您不能再使用(没有引用的)对象,仅此而已。 - dimo414