两个私有子类中的相同类型变量不被识别为相同

Same type variable in two private subclasses not recognized as same

在对实现数据结构进行了一些研究后,我发现在尝试使用与父项相同的通用 class 制作两个子 class 时出现问题。

我以前没有发现这个问题,因为我通常避免做私有子classes,虽然这次我想做一个快速测试并发现了这个。

我可以在没有 Node<T> 作为 current 类型的情况下使它工作,但是 Node,然后转换为 T。但我想知道为什么编译器不理解它与 Node.js 中的 T 相同。它认为 Node 中的 TLinkedStackIterator 中的 T 是两个不同的 T,即使 node 中的 T 被识别为 T LinkedStack.

public class LinkedStack<T> implements Iterable<T>{
    private Node<T> first = null;

    private class Node<T>{
        private T       item;
        private Node    next;
    }

    private class LinkedStackIterator<T> implements Iterator<T>{
        private Node<T> current = first; //Error here

        public boolean hasNext() { return current.next == null; }
        public void     remove() { throw new UnsupportedOperationException(); }
        public T        next()
        {
            T item      = current.item;
            current     = current.next;
            return item;
        }
    }
}

Error: incompatible types: LinkedStack<T#1>.Node<T#1> can not be converted to LinkedStack<T#1>.LinkedStackIterator<T#2> where T#1 and T#2 are type variables.
T#1 extends Object in LinkedStack
T#2 extends Object in LinkedStack.LinkedStackIterator.

感谢您的帮助。

在这里声明两个不同的 T类型:

public class LinkedStack<T> implements Iterable<T>{
     ...
    private class LinkedStackIterator<T> implements Iterator<T>{
    ...
}

所以这条语句无法编译:

 private Node<T> current = first;

因为 first 变量指的是与 current 变量不同的类型。
first 指的是 LinkedStackTcurrent 指的是 LinkedStackIteratorT

要允许两个 class 使用相同的 T 类型,不要在内部 class 中再次声明 T 而是重用一个在外部声明 class :

private class LinkedStackIterator implements Iterator<T>{

您不需要将通用类型添加到第二个 class、LinkedStackIterator。它将继承外部 class.

的类型

请注意,尽管使用相同的名称 T,但对于类型参数,它将是一个 与外部 class 不同的 参数。同样的道理,在第一个内层classNode中,最好给参数取一个不同的名字,例如Node<U>,让区别一目了然。

以下代码对我来说编译得很好(在制作 LinkedStack 抽象之后):

public abstract class LinkedStack<T> implements Iterable<T>{
    private Node<T> first = null;

    private class Node<U>{
        private U       item;
        private Node<U>    next;
    }

    private class LinkedStackIterator implements Iterator<T>{
        private Node<T> current = first; //Error here

        public boolean hasNext() { return current.next == null; }
        public void     remove() { throw new UnsupportedOperationException(); }
        public T        next()
        {
            T item      = current.item;
            current     = current.next;
            return item;
        }
    }
}

泛型T继承自LinkedStack<T>class
所以 Node

有两种可能的定义

我更喜欢这个——注意 static

private static class Node<T> {
  private T item;
  private Node<T> next;
}

如果您出于某些原因需要 Node 是非静态的
(只有 item 类型必须是 T )

private class Node {
  private T item;
  private Node next;
}