泛型集合实现java编译错误

发布于 2025-01-06 08:26:00 字数 1086 浏览 3 评论 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;
        }

        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>

这是什么意思?我该如何解决这个问题?

顺便说一句,代码只是实现的一部分,所以不要试图从逻辑上弄清楚它。

EDIT :

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

the problem is that i get the following compilation Error on the emphasized lines :

> Type mismatch: cannot convert from LinkedList<E>.Node<E> to
> LinkedList<E>.Node<E>

what does it mean? and how do i fix this?

btw, the code is only part of the implementation so dont try to logicly figure it out.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

臻嫒无言 2025-01-13 08:26:00

--- 随着问题略有变化而编辑 ---

现在的问题是,我如何让两个内部类协调泛型类型?简而言之,如果它们都是绑定泛型类型的外部类的内部类,则不必这样做。因此,即使使用非泛型 LinkedListIterator 中的 public synchronized E get() ,您也会返回一个 E (并且它是类型安全的)。

但是,如果您随后尝试实现 java.util.Iterator ,事情就会崩溃,因为 E 基于不同的类(接口),因此 E具有不同的范围。你如何解决这个问题?您需要将 Node 类参数化为 Node 以满足 E 绑定存在于 Iterator 即使该实现在其原始类的范围之外使用。这强制静态定义Node

它强制 Node 进行静态定义的原因与垃圾收集有关。即使 LinkedList 已计划进行垃圾回收,迭代器仍可能保留对 Node 的引用。当然,您也许能够通过特定的实现来防止这种情况发生,但 JVM 必须允许任何实现(甚至是错误的实现)。

也许用代码来解释会更容易,

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

  }

如果你不小心,你现在可能会回到开始的地方;然而,关键是在父作用域中需要时构造新的 Node 对象。由于这与构造 LinkedIterator 类型的范围相同,因此将确保泛型类型安全。

--- 原帖如下 ----

通过指定您的节点类定义是 Node,您基本上创建了第二个独立作用域的泛型类型 E ,它将隐藏 LinkedList 类中的外部泛型类型 E

由于您的类都不是静态的,因此它们仅存在于 LinkedList 类的上下文中,该类将提供泛型绑定。这意味着您可以将 Node 简化为 Node,但仍将 E 类类型放入 Node 类中。 LinkedListIterator 也是如此,只不过如果您希望它实现 Iterator,您应该指示它实现 Iterator

由于请求,以下是在我的机器上编译的代码,(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;
        }
    }
}

--- Edited as the question changes slightly ---

The question is now becoming, how do I have two inner classes coordinate generic types? In short, they don't have to if they are both inner classes of an outer class where the generic type is bound. So even with the public synchronized E get() in the non-generic LinkedListIterator you are returning an E (and it is type safe).

However, if you then reach out to implement java.util.Iterator<E> things fall apart, because that E is based on a different class (interface) so the E has different scoping. How do you fix this? You need to parameterize your Node classes to Node<E> to satisfy that E bindings exist on the implementation of Iterator even when that implementation is being used outside of the scope of it's originating class. This forces Node<E> to be defined statically.

The reason it forces the static definition of Node<E> has to do with garbage collection. An Iterator might still be holding references to Nodes even though the LinkedList is scheduled for garbage collection. Sure, you might be able to keep such a thing from happening with a specific implementation, but the JVM has to allow any implementation (even an errant one).

Perhaps it is easier to explain with code

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

  }

If you are not careful, you can now wind up back where you started; however, the key is to construct new Node<E> objects when needed in the parent scope. Since that is the same scope where you construct LinkedIterator types, the generic type safety will be ensured.

--- Original post follows ----

By specifying that your node class definition is a Node<E>, you basically create a second, independently scoped generic type E which will hide the outer generic type E in the LinkedList class.

Since none of your classes are static, they will only exist within context of a LinkedList class, which will provide the generics binding. That means you can simplify Node<E> to Node yet still put E class types within the Node class. Same goes for the LinkedListIterator, except that if you want it to implement Iterator you should indicate it implements Iterator<E>.

Due to request, what follows is the code that compiles on my machine, (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;
        }
    }
}
嗫嚅 2025-01-13 08:26:00

通过参数化嵌入的类,您做得有点过头了。我删除了所有不必要的。

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

You overdid it a bit by parametrising the embedded classes. I removed all unnecessary ones.

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

Alternatively with a static class 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;
        }
    }
}
南风几经秋 2025-01-13 08:26:00

它不明白是在 LinkedListIterator 中是相同的作为父类。只需从内部类中删除:

    public class LinkedListIterator {
        private Node<E> current = null;

        public synchronized void resetToHead() {
            current = head.next;
        }

        public synchronized void resetToTail() {
            current = tail.prev;
        }
    }

It doesn't understand that the <E> in LinkedListIterator is the same <E> as the parent class. Just remove from the inner class:

    public class LinkedListIterator {
        private Node<E> current = null;

        public synchronized void resetToHead() {
            current = head.next;
        }

        public synchronized void resetToTail() {
            current = tail.prev;
        }
    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文