编辑:
public class LinkedList<E> {
private class Node {
protected Node next, prev;
protected E data;
protected Node(E dat) {
data = dat;
next = prev = null;
}
}
private Node head, tail;
public LinkedList() {
(head = new Node(null)).next = tail = new Node(null);
tail.prev = head;
tail.next = head.prev = null;
}
public class LinkedListIterator {
private Node current = null;
public synchronized void resetToHead() {
current = head.next;
}
public synchronized void resetToTail() {
current = tail.prev;
}
public synchronized E get() {
if (current!=null) return current.data;
return null;
}
}
}
问题是我在强调的行上得到以下编译错误:
> Type mismatch: cannot convert from LinkedList<E>.Node<E> to
> LinkedList<E>.Node<E>
这是什么意思?以及如何解决这个问题?
顺便说一下,代码只是实现的一部分,所以不要试图逻辑地解决它。
答案 0 :(得分:2)
---编辑问题略有改变---
现在的问题是,如何让两个内部类协调泛型类型?简而言之,如果它们都是泛型类型绑定的外部类的内部类,则它们不必。因此,即使使用非通用public synchronized E get()
中的LinkedListIterator
,您也会返回E
(并且它是类型安全的)。
但是,如果你接触实现java.util.Iterator<E>
事情就会崩溃,因为E基于不同的类(接口),因此E
具有不同的范围。你是如何解决这个问题的?您需要将Node
类参数化为Node<E>
,以满足E
Iterator
实现上存在的Node<E>
绑定,即使该实现正在其原始范围之外使用类。这会强制Node<E>
静态定义。
它强制Node
的静态定义的原因与垃圾收集有关。尽管LinkedList
被安排用于垃圾收集,但迭代器可能仍然保持对 public LinkedList<E> {
public Iterator<E> iterator() {
return new LinkedIterator(head);
}
// private because we don't want instances created outside of this LinkedList
private class LinkedIterator implements Iterator<E> {
// Right here, needing a parameterized next node will force Node to be static
// static inner classes can exist outside of the scope of their parent
// Since it can exist outside of the parent's scope, it needs it's own generic parameter
private Node<E> next;
LinkedIterator(Node start) {
next = start;
}
public boolean hasNext() {
return next != null;
}
public E next() {
Node<E> retValue = next;
if (retValue != null) {
next = retValue.next;
}
return retValue;
}
}
// must be static because LinkedList might be garbage collected when
// an Iterator still holds the node.
// This E is not the same E as in LinkedList, because it is a E declaration (hiding the above E)
private static Node<E> {
Node<E> next;
Node<E> prev;
E data;
}
}
的引用。当然,您可能能够通过特定实现来防止这种情况发生,但JVM必须允许任何实现(即使是错误的实现)。
也许用代码解释更容易
Node<E>
如果你不小心,你现在可以回到你开始的地方;但是,关键是在父作用域中需要时构造新的Node<E>
对象。由于这与构造LinkedIterator类型的范围相同,因此将确保通用类型安全。
---原帖如下----
通过指定您的节点类定义是E
,您基本上创建了第二个独立范围的泛型类型E
,它将隐藏{{1}中的外部泛型类型LinkedList
}。class。
由于您的类都不是静态的,因此它们只存在于LinkedList类的上下文中,这将提供泛型绑定。这意味着您可以将Node<E>
简化为Node
,但仍将E
类类型放在Node
类中。同样适用于LinkedListIterator
,但如果您希望它实现Iterator
,则应指明它实现Iterator<E>
。
由于请求,以下是在我的机器上编译的代码,(java 1.6.0_20)
public class LinkedList<E> {
private class Node {
protected Node next, prev;
protected E data;
protected Node(E dat) {
data = dat;
next = prev = null;
}
}
private Node head, tail;
public LinkedList() {
(head = new Node(null)).next = tail = new Node(null);
tail.prev = head;
tail.next = head.prev = null;
}
public class LinkedListIterator {
private Node current = null;
public synchronized void resetToHead() {
current = head.next;
}
public synchronized void resetToTail() {
current = tail.prev;
}
}
}
答案 1 :(得分:0)
通过参数化嵌入式类,你有点过分了。我删除了所有不必要的内容。
public class LinkedList<E> {
private class Node {
protected Node next, prev;
protected E data;
protected Node(E dat) {
data = dat;
next = prev = null;
}
}
private Node head, tail;
public LinkedList() {
(head = new Node(null)).next = tail = new Node(null);
tail.prev = head;
tail.next = head.prev = null;
}
public class LinkedListIterator {
private Node current = null;
public synchronized void resetToHead() {
current = head.next;
}
public synchronized void resetToTail() {
current = tail.prev;
}
}
}
或者使用静态类Node。
public class LinkedList<E> {
private static class Node<E2> {
protected Node next, prev;
protected E2 data;
protected Node(E2 dat) {
data = dat;
next = prev = null;
}
}
private Node<E> head, tail;
public LinkedList() {
(head = new Node(null)).next = tail = new Node(null);
tail.prev = head;
tail.next = head.prev = null;
}
public class LinkedListIterator {
private Node<E> current = null;
public synchronized void resetToHead() {
current = head.next;
}
public synchronized void resetToTail() {
current = tail.prev;
}
}
}
答案 2 :(得分:0)
不理解&lt; E&gt;在LinkedListIterator中是相同的&lt; E&gt;作为父类。只需从内部类中删除:
public class LinkedListIterator {
private Node<E> current = null;
public synchronized void resetToHead() {
current = head.next;
}
public synchronized void resetToTail() {
current = tail.prev;
}
}