2011-08-21 113 views
1

我只是做一些练习,从我的书之一,我很好奇为什么我收到以下错误在日食:无法将节点<E>转换成节点<E>?

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

代码:

import java.util.Iterator; 
    import java.util.ListIterator; 
    import java.util.NoSuchElementException; 


public class DoublyLinkedList<E extends Comparable<E>> implements Iterable<E>{ 

private int size = 0; 
private Node<E> head; 
private Node<E> tail; 

/** Returns a list iterator object for the list at 
* the specified index 
*/ 

public DoublyLinkedList(){ 


} 



private static class Node<E> { 

    Node<E> next = null; 
    Node<E> prev = null; 
    E data; 

    public Node(E dataItem){ 
     data = dataItem; 
    } 

    public Node(E dataItem, Node<E> previous, Node<E> nextNode){ 
     this(dataItem); 
     prev = previous; 
     next = nextNode; 
    } 

} 


private class MyListIter<E> implements ListIterator<E>{ 

    private Node<E> lastReturned; // a link reference to the last item that was returned 
    private Node<E> nextItem; // a link reference to the next item in the list 
    /** The index of the current position */ 
    private int index = 0; 

    public MyListIter(int pos){ 
     if (pos < 0 || pos > size) 
      throw new IndexOutOfBoundsException("Invalid index: " + index); 
     lastReturned = null; 
     if (pos == size){ 
      index = size; 
      nextItem = null; 
     } else { // otherwise we will start at the beginning of the list, and loop until the position in the argument 
      nextItem = head; // ERROR 
      for (index = 0; index < pos; index++){ 
       nextItem = nextItem.next; // next item will always reference the list node that is called by the next method 
      } 

     } 
    } 

    @Override 
    public void add(E element) { 
     if (head == null){ 
      Node<E> newNode = new Node<E>(element); 
      head = newNode; // ERROR 
      tail = head; 
     } 


    } 
    @Override 
    public boolean hasNext() { 
     return nextItem != null; // just checks to make sure there is a node following the current node 
    } 
    @Override 
    public boolean hasPrevious() { 
     return (nextItem == null && size != 0) || nextItem.prev != null; 
    } 
    @Override 
    public E next() { 
     if (!hasNext()) 
      throw new NoSuchElementException("There is no node at that location"); 
     lastReturned = nextItem; 
     nextItem = nextItem.next; 
     index++; 
     return lastReturned.data; 
    } 
    @Override 
    public int nextIndex() { 
     // TODO Auto-generated method stub 
     return 0; 
    } 
    @Override 
    public E previous() { 
     if (!hasPrevious()) 
      throw new NoSuchElementException(); 
     if (nextItem == null) // the iterator is at the end of the list 
      nextItem = tail; // therefore, the nextItem is at the tail, so the previous is the tail. ERROR HERE TOO 
     else 
      nextItem = nextItem.prev; 
     lastReturned = nextItem; 
     index--; 
     return lastReturned.data; 
    } 
    @Override 
    public int previousIndex() { 
     // TODO Auto-generated method stub 
     return 0; 
    } 
    @Override 
    public void remove() { 
     // TODO Auto-generated method stub 

    } 
    @Override 
    public void set(E arg0) { 
     // TODO Auto-generated method stub 

    } 



} 


@Override 
public Iterator<E> iterator() { 
    // TODO Auto-generated method stub 
    return null; 
} 


} 

我作了评论正是我在3个不同的位置得到错误。如果你能提供任何反馈,我会很感激。我的书没有解决它,我已经搜索过,并且看起来无法得到我正在寻找的答案。

回答

5

您已经定义了两个不同的泛型类型:E(为Node)和E extends Comparable<E>(用于DoublyLinkedList)。

这里的主要问题可能是MyListIter,这是一个非静态的内部类,因此它会自动继承EDoublyLinkedList的定义。因为它继承了E的定义,你应该只被声明为

private class MyListIter implements ListIterator<E> 

,但你做了它MyListIter<E>,这是重新定义E到的东西比EDoublyLinkedList用户不同(隐式E extends ObjectE extends Comparable<E>) 。

认为Node将正常运行,是因为它是一个嵌套类(与static关键字),并没有从DoublyLinkedList继承E定义。但是,它很可能是有意义这里将其声明为一个非静态内部类的DoublyLinkedList(​​)一样MyListIter

此外,你应该让E是一个类型,它是某种类型的通过声明为E extends Comparable<? super E>实现Comparable亚型

+0

+1好点关于'E extends Comparable ' –

+0

哇。我永远不会知道。我认为这固定了一切。这本书写得很糟糕。我的印象是,如果DoublyLinkedList类型为,则该类别中的所有内容也应该是,使它们全部属于同一类型。但我猜它不是? – TMGunter

+2

@TMGunter:如果声明了一个不带'static'关键字的内部类,则该内部类的所有实例都必须属于包含类的特定_instance_。因此,它们自动访问为包含类声明的泛型类型(在这种情况下为'E')。我实际上不确定'Node'在这里是一个问题,因为它有'static'关键字,因此它是一个嵌套类,它不会继承'E'的定义。 'MyListIter'在这里可能是真正的问题,因为它继承了'E'的定义,但也声明了它自己的(冲突的)定义。 – ColinD

3

看起来你得到这个错误是因为你在你的Node嵌套类中重新定义了E。由于它是一个静态嵌套类,它与父类DoublyLinkedList没有直接关系。让这个类非静态变得更有意义,这样E就继续有它的意义。例如:

private class Node { 

Node next = null; 
Node prev = null; 
E data; 

... 

编辑:如ColinD指出,MyListIter应同样不重新声明E作为类型参数。改变这个像Node应该解决这个问题。

+0

当我这样做,它抱怨不是一般的我的节点构造和说,“型DoublyLinkedList .Node不是通用的;它不能与参数参数” – TMGunter

+0

你一定要改变这一切'节点'类型到'Node'? –

+0

是的。节点现在是类型节点。我还用科林的建议使E成为了一个子类型。我的书完全没有涉及,但我想我理解它的含义。我必须查看它。它使我更加有意义的是,让Node成为一个私有的嵌套类,并移除它的静态属性。我试图追踪我的书,我认为它的教学效果并不好。 – TMGunter

1

ColinD是对的(+1)。

要了解发生了什么事情,试想没有使用相同的形式类型参数的3倍,而E代表DoublyLinkedList,F为节点和G为MyListIter。然后错误信息会说Type mismatch: cannot convert from type DoublyLinkedList.Node<E> to DoublyLinkedList.Node<G>。 ColinD建议的解决方案是。如果你愿意,你可以离开Node<F>静态,修复所有实例将具有相同的实际类型参数。

+0

所以我真的可以定义任何类型的静态类“节点”我真的想要?当我在顶级类中使用对节点的引用时,即使节点被定义为节点,它将继承父类的类型“E”?这就是我正在收集的内容。如果我不使它成为一个静态的内部类,我不应该使用类型参数定义节点,因为类型“E”将从最顶级的类继承而来。 – TMGunter

+0

@TMGunter:是的,是的。 – DaveFar

+0

为了清楚起见:在'public class DoublyLinkedList head;',就像例如'private Node head;'或'private List head;'一样。就像List的正式类型参数完全独立于你的'E'并且可能是'F'或其他任何东西一样,''private static class Node '的形式类型参数是。这就是为什么我建议使用不同的字母,以避免混淆。 – DaveFar