我回头看了一些写在不同迭代器所需位置的代码,我注意到我像平常一样写了第一个迭代器:

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()。这比较简单,而且总是可取的。

07-24 09:19