我回头看了一些写在不同迭代器所需位置的代码,我注意到我像平常一样写了第一个迭代器:
private class Traverse implements Iterator {
int pos = 0;
boolean hasNextCalled = false;
@Override
public boolean hasNext() {
hasNextCalled = true;
if(pos<size()) {
return true;
} else {
return false;
}
}
@Override
public Card next() {
return cards.get(pos++);
}
@Override
public void remove() {
if (!hasNextCalled) {
throw new IllegalStateException("hasNext() must be called before remove()");
}
if(pos<1) {
throw new IllegalStateException();
}
cards.remove(--pos);
hasNextCalled = false;
}
}
然后通过创建新的Traverse对象但覆盖所有方法来实现第二个迭代器:
public Iterator OddEvenIterator() {
Iterator it = new Traverse(){
private int pos = 0;
boolean hasNextCalled = false;
@Override
public boolean hasNext() {
hasNextCalled = true;
if (pos < size()) {
return true;
} else {
return false;
}
}
@Override
public Card next() {
Card nextCard = cards.get(pos);
pos+=2;
boolean moreCards = hasNext();
if(moreCards==false) {
pos=1;
}
return nextCard;
}
@Override
public void remove() {
if (!hasNextCalled) {
throw new IllegalStateException("hasNext() must be called before remove()");
}
if (pos < 1) {
throw new IllegalStateException();
}
pos-=2;
cards.remove(pos);
hasNextCalled = false;
}
};
return it;
}
我不记得为什么要这么做,但是这样做感觉很糟糕。我想知道这两种方法之间是否有有效的区别?
最佳答案
第二种方法创建一个扩展Traverse
的匿名类,这意味着您可以访问其成员(当然,请考虑正常的可见性规则)。但是,然后您shadow声明了Traverse
的两个成员,这意味着匿名类将不会使用它们。
假设您定义了每个Iterator
方法并将返回值键入为Iterator
,则没有理由扩展类而不是直接实现Iterator
,除非您需要访问该类提供的某些成员。由于在这种情况下不这样做,因此没有理由扩展Traverse
。
此外,除了Traverse
方法之外,Iterator
没有定义任何其他方法,因此在将从OddEvenIterator
返回的迭代器向下转换为Traverse
时,甚至没有任何用处。如果有的话,这可能是扩展它的原因-尽管它也可能是代码的味道。
扩展Traverse
的唯一其他原因是,如果其他一些代码使用反射来检查Traverse
的子类型(包括使用instanceof
)。再次,这可能是代码的味道-但这是有可能的。
我会建议一些样式方面的事情,顺便说一句:
您应该使用generics而不是原始的Iterator
类型
大多数Java约定的方法名称以小写开头(因此,oddEvenIterator()
)
在hasNext
(而不是if-else
)中,您只能使用return pos < size()
。这比较简单,而且总是可取的。