为啥即使实现了 Iterable,我也会收到 foreach 编译器错误?

Posted

技术标签:

【中文标题】为啥即使实现了 Iterable,我也会收到 foreach 编译器错误?【英文标题】:Why do I get a foreach compiler error even though Iterable is implemented?为什么即使实现了 Iterable,我也会收到 foreach 编译器错误? 【发布时间】:2019-05-22 04:53:37 【问题描述】:

我正在尝试在 OOP 中学习不同的设计模式,而我目前正在学习的是迭代器模式。因此我制作了两个自己的接口(Iterable 和 Iterator)。

我正在尝试迭代 List<Person> friends。但是行:for (Person p : p1) 给出以下编译器错误:

foreach not applicable to type 'com.company.Person'

这对我来说毫无意义,因为我已经实现了 Iterable 并在我所见的范围内覆盖了 iterator() 方法。

谁能告诉我我错过了什么?

这是我的代码:

主类:

Person p1 = new Person("Erik");
    p1.addFriend("Lars");
    p1.addFriend("Jenny");
    p1.addFriend("Janne");


    for (Person p : p1) 
        System.out.println(p.name);
    

迭代器:

public interface Iterator<T> 

    boolean hasNext();

    T next();

    void remove();

可迭代:

public interface Iterable<T> 
    Iterator<T> iterator();

人:

public class Person implements Iterable<Person>
    private List<Person> friends = new ArrayList<>();
    String name;
    int index = 0;
    public Person(String name)
        this.name = name;
    

    public void addFriend(String name)
        friends.add(new Person(name));
    

    @Override
    public Iterator<Person> iterator()
        return new Iterator<Person>() 
            //int index = 0;
            @Override
            public boolean hasNext() 
                System.out.println(index);
                return index < friends.size();

                

            @Override
            public Person next() 
                if(hasNext())
                    return friends.get(index++);
                
                else
                    return null;
                
            
            @Override
            public void remove() 
                if(index<=0) 
                    friends.remove(index--);
                
            
        ;
    

【问题讨论】:

好像您创建了自己的Iterable&lt;...&gt; 界面? foreach 仅适用于java.lang.Iterable 另外,Person 是不可迭代的。 Person集合是。如果您已经拥有Person 的集合(就像您所做的那样),那么您应该已经能够迭代该集合。 换句话说,它应该是for (Person p : friends) // do something with p ,读作“对于你的friends集合中的每个Person p,用p做一些事情” 【参考方案1】:

看起来您已经定义了自己的IteratorIterable 接口。这不是 foreach 循环在 Java 中的工作方式。

要使一个类成为 foreach 循环的可行目标,它必须实现内置的 Iterable,参见 java.lang.Iterable。移除你自己的IteratorIterable接口,实现内置的Iterable(同时使用内置的Iterator)。

此外,就您的语义而言,将Person 类设为Iterable 可能没有多大意义。该人的朋友的收藏应该是Iterable。相反,您可能希望通过 getFriends() 方法公开朋友的集合,该方法将返回该列表的不可修改视图 (Collections.unmodifiableList(friends))。该列表已经是Iterable,让您无需首先实现它。

【讨论】:

是的,我想我记得我的老师是这样做的,这就是为什么我专门尝试实现我自己的书面界面。再次仔细检查了他的讲座后,似乎他确实使用了现有的界面。我认为他出于某种教育目的开设了自己的课程,然后又回到了现有的课程中。关于获取 unmodifiableList 的智能提示。我会记住的。这个例子只需要一个实现 Iterable 的类来测试它是如何工作的。

以上是关于为啥即使实现了 Iterable,我也会收到 foreach 编译器错误?的主要内容,如果未能解决你的问题,请参考以下文章

为啥即使我使用 sparse_categorical_crossentrpy,我也会收到“收到超出 [0, 1) 有效范围的标签值 6”?

为啥即使在包含 math.h 并使用 -lm 链接到数学库之后我也会收到“未定义的符号:.sqrtf”

为啥即使我修改了 lock 变量,我也会得到一个无限的 while 循环? [复制]

AngularJS:为啥即使显示正确,我也会得到 NaN?

为啥即使存在列,我也会有 ORA-00904?

即使代码在 try/catch 块中,我也会不断收到异常 [关闭]