这个问题的启发:如何实现可迭代 我决定做一个基本的链表实现并实现一个迭代器,以便有一个这样的代码:
MyList<String> myList = new MyList<String>();
myList.add("hello");
myList.add("world");
for(String s : myList) {
System.out.println(s);
}
代码并不难处理,创建了一个带有private static class Node<T>
和private class MyListIterator<T> implements Iterator<T>
的class MyList<T> implements Iterable<T>
,但是后来我在实现自己的Iterator#remove
版本时遇到了一个问题:
class MyList<T> implements Iterable<T> {
private static class Node<T> {
//basic node implementation...
}
private Node<T> head;
private Node<T> tail;
//constructor, add methods...
private class MyListIterator<T> implements Iterator<T> {
private Node<T> headItr;
private Node<T> prevItr;
public MyListIterator(Node<T> headItr) {
this.headItr = headItr;
}
@Override
public void remove() {
//line below compiles
if (head == headItr) {
//line below compiles
head = head.getNext();
//line below doesn't and gives me the message
//"Type mismatch: cannot convert from another.main.MyList.Node<T> to
//another.main.MyList.Node<T>"
head = headItr.getNext();
//line below doesn't compile, just for testing purposes (it will be deleted)
head = headItr;
}
}
}
}
这条错误消息引起了我的好奇心。我在网上寻找这个问题,但一无所获(或者可能我不擅长搜索此类问题(。比较同一类型的两个变量但不能相互分配的原因是什么?
顺便说一下,我知道我可以只查看LinkedList
的代码并检查 Java 设计人员如何实现它并将其复制/粘贴/适应我自己的实现,但我更喜欢对真正的问题进行解释和理解。
显示我当前MyList
类实现的完整代码:
class MyList<T> implements Iterable<T> {
private static class Node<T> {
private T data;
private Node<T> next;
public Node(T data) {
super();
this.data = data;
}
public T getData() {
return data;
}
public Node<T> getNext() {
return next;
}
public void setNext(Node<T> next) {
this.next = next;
}
}
private Node<T> head;
private Node<T> tail;
private int size;
public MyList() {
head = null;
tail = null;
}
public void add(T data) {
Node<T> node = new Node<T>(data);
if (head == null) {
head = node;
tail = head;
} else {
tail.setNext(node);
tail = node;
}
size++;
}
private class MyListIterator<T> implements Iterator<T> {
private Node<T> headItr;
private Node<T> prevItr;
public MyListIterator(Node<T> headItr) {
this.headItr = headItr;
}
@Override
public boolean hasNext() {
return (headItr.getNext() != null);
}
@Override
public T next() {
T data = headItr.getData();
prevItr = headItr;
if (hasNext()) {
headItr = headItr.getNext();
}
return data;
}
@Override
public void remove() {
if (head == headItr) {
//problem here
head = headItr.getNext();
}
//implementation still under development...
}
}
@Override
public Iterator<T> iterator() {
return new MyListIterator<T>(head);
}
}
这是问题所在:
class MyList<T> implements Iterable<T> {
private class MyListIterator<T> implements Iterator<T> {
...
}
}
(在你的精简版本中,你已经MyList
非通用的,这无济于事。
此时,有两种不同的T
类型变量 - 一个在嵌套类中,一个在外部类中。你不需要Node
是通用的 - 你只需要:
class MyList<T> implements Iterable<T> {
private class MyListIterator implements Iterator<T> {
...
}
}
现在只有一个T
- 外部类中的那个。这不像您希望列表迭代器具有与封闭实例中声明的T
不同的,因此您不希望它是泛型的。
换句话说:尝试在具有不同名称的类型参数中使MyListIterator
泛型,然后就会更清楚出了什么问题,因为这两个名称在错误消息中是可区分的。它有效地:
Type mismatch: cannot convert from another.main.MyList.Node<TOuter> to
another.main.MyList.Node<TInner>
(反之亦然(。
迭代器应声明为
private class MyListIterator implements Iterator<T>
而不是作为
private class MyListIterator<T> implements Iterator<T>
通过将其声明为 MyListIterator,其泛型类型 T 与其封闭类中的 T 不同。
从 MyListIterator
的声明中删除类型参数:
private class MyListIterator implements Iterator<T>
和电话iterator()
public Iterator<T> iterator() {
return new MyListIterator(head);
}
在当前版本中,MyListIterator
的 T 与 MyList
中的 T 不同。
其他三个是对的:你需要改变private class MyListIterator<T> implements Iterator<T>
自private class MyListIterator implements Iterator<T>
但是一旦你这样做了,你还需要改变你的iterator()
方法:
public Iterator<T> iterator() {
return new MyListIterator(head); //was 'return new MyListIterator<T>();'
}
否则,您将收到另一个错误。进行第二次更改后,它应该可以工作。