泛型集合实现java编译错误

时间:2012-02-17 22:20:59

标签: java generics compilation

编辑:

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>
这是什么意思?以及如何解决这个问题?

顺便说一下,代码只是实现的一部分,所以不要试图逻辑地解决它。

3 个答案:

答案 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;
        }
    }