尝试在Java中实现Iterable时使用泛型时出错

时间:2012-06-09 00:11:53

标签: java generics iterator iterable

任何人都可以解释我收到此错误的原因吗?

这是我使用双向链表实现的堆栈类:

import java.util.Iterator;

public class Stack<Item> implements Iterable<Item>{

private Node first;
private int N;

private class Node{
    private Node next;
    private Node prev;
    private Item item;
}

public Iterator<Item> iterator(){
    return new ReverseIterator<Item>();
}    

private class ReverseIterator<Item> implements Iterator<Item>{
    private Node x;

    private ReverseIterator(){
        if (first != null)
           x = first.prev;
    }

    public boolean hasNext(){
        return x != null;
    }

    public Item next(){
        Item i = x.item;
        x = x.prev;
        return i;
    }

    public void remove(){
    }
}

public void push(Item i){
    if (isEmpty()){
        first = new Node();
        first.item = i;
        first.next = first;
        first.prev = first;
    }
    else{
        Node x = new Node();
        x.item = i;
        x.next = first;
        x.prev = first.prev;
        first.prev.next = x;
        first.prev = x;
    }
    N++;
}

public Item pop(){
    assert !isEmpty() : "Stack is empty";

    Item i = first.prev.item;
    if (N == 1)
        first = null;
    else{
        first.prev.prev.next = first;
        first.prev = first.prev.prev;
    }

    N--;    
    return i;
}

public boolean isEmpty(){
    return N == 0;
}

public int size(){
    return N;
}

public static void main(String[] args){

}
}

编译器说Item i = x.item;,期望的Item,找到Item有错误。解决方案是将ReverseIterator<Item>替换为ReverseIterator。有人可以解释为什么我通过添加<Item>得到了错误吗?

由于

3 个答案:

答案 0 :(得分:4)

仅仅因为您对类型变量(Item)使用相同的名称并不意味着它代表相同的泛型类型。

如果在通用类N<T>中声明嵌套类C<T>T中的C<T>实际上会隐藏在N<T>的正文中。它与声明名为x的类级别字段并在该类中声明方法参数(也称为x)的原理完全相同。你内心的声明范围隐藏了任何东西。

如果ReverseIterator static 嵌套类,则必须将<Item>添加到其声明中,因为它的实例不会包含Stack<Item> {1}}。并且会导致相同的错误,即使在这种情况下也不会隐藏。实际上,您还需要将类型变量添加到Node

答案 1 :(得分:1)

你的问题在这里:

private class ReverseIterator<Item> implements Iterator<Item>{

在这里,您要定义一个处理类型为Item的对象的内部类,但此类型与封闭的Item类的Stack类型不同。因此,当您执行Item i = x.item; x.item类型为Stack.Item时(某种类型),i类型为Stack.ReverseIterator.Item

你有两个选择,一个是你要做的事情,让内部类使用与外部相同的Item类型,或者你可以创建内部类static并保持自己的内部Item类型(虽然在这种情况下我会建议为内部类型使用不同的名称,否则您会发现自己再次感到困惑。)

答案 2 :(得分:0)

试试这样:

import java.util.Iterator;

public class Stack<Item> implements Iterable<Item> {

    private Node first;
    private int N;

    private class Node {
        private Node next;
        private Node prev;
        private Item item;
    }

    @Override
    public Iterator<Item> iterator() {
        return new ReverseIterator();
    }

    private class ReverseIterator implements Iterator<Item> {
        private Node x;

        private ReverseIterator() {
            if (first != null) {
                x = first.prev;
            }
        }

        public boolean hasNext() {
            return x != null;
        }

        public Item next() {
            Item i = x.item;
            x = x.prev;
            return i;
        }

        public void remove() {
        }
    }

    public void push(final Item i) {
        if (isEmpty()) {
            first = new Node();
            first.item = i;
            first.next = first;
            first.prev = first;
        } else {
            Node x = new Node();
            x.item = i;
            x.next = first;
            x.prev = first.prev;
            first.prev.next = x;
            first.prev = x;
        }
        N++;
    }

    public Item pop() {
        assert !isEmpty() : "Stack is empty";

        Item i = first.prev.item;
        if (N == 1) {
            first = null;
        } else {
            first.prev.prev.next = first;
            first.prev = first.prev.prev;
        }

        N--;
        return i;
    }

    public boolean isEmpty() {
        return N == 0;
    }

    public int size() {
        return N;
    }

    public static void main(final String[] args) {

    }
}