【问题标题】:Why I get StackOverflowError when I use foreach?为什么我在使用 foreach 时会收到 StackOverflowError?
【发布时间】:2017-12-21 06:48:54
【问题描述】:

我有这个界面:

public interface ExpIterator extends Iterator<DNAChain> {
    void setLevel(int n);
}

还有这个类:

public class DNAChain {
    private  String  Chain;
    private  boolean natural;

    public String getChain() {
        return Chain;
    }

    public  DNAChain (String  Chain, boolean natural) {
        this.Chain = Chain;
        this.natural = natural;
    }  
}

还有这个类:

public class Experiment implements ExpIterator,Iterable{

    private DNAChain[] Chains; // Chains found in the experiment
    private int counter; // next  chain  index

    public DNAChain[] getChains() {
        return Chains;
    }

    public void setChains(DNAChain[] chains) {
        Chains = chains;
    }

    public  Experiment () {}

    public  Experiment (int  n) {
        Chains  = new DNAChain[n];
    }

    @Override
    public void setLevel(int n) {
    }

    @Override
    public boolean hasNext() {
        return counter < Chains.length;
    }

    @Override
    public DNAChain next() {
        return Chains[counter++];
    }

    @Override
    public void remove() {
    }

    @Override
    public Iterator iterator() {
      return this.iterator();
    }
}

如您所见,Experiment 类实现了 Iterable 接口,因此我可以使用 foreach。

但是当我尝试在 Experiment 对象上使用 foreach 时:

     Experiment experiment1 = new Experiment(5);

     for (Object o :experiment1) {
          System.out.println("ddd");
         ((DNAChain)o).getChain();
       }

我收到此错误:

Exception in thread "main" java.lang.StackOverflowError
    at Experiment.iterator(Experiment.java:72)
    at Experiment.iterator(Experiment.java:72)
    at Experiment.iterator(Experiment.java:72)

我的代码有什么问题?我做错了什么?

【问题讨论】:

  • return this.iterator(); - 你认为这是做什么的?
  • 当然,您在这里已经足够长的时间了,知道在在这里提出这样的问题之前您真的应该进行调试尝试。
  • 在那个注释中,这似乎是一系列低效问题中的最新一个,这些问题都被否决了。我的理解是,如果持续时间更长,这最终会导致被 SO 屏蔽。

标签: java


【解决方案1】:

您的方法 Experiment.iterator 在无限递归中调用自己。

如果您使用的是 Java 8,您可以这样做:

@Override
public Iterator iterator() { Arrays.stream(chains).iterator(); }

【讨论】:

  • 迈克感谢您的来信。如何返回迭代器链数组?我必须自己实现吗?
  • 我认为有几种方法,您可以查看其他帖子并使用您更喜欢的选项stackoverflow.com/questions/10335662/…
  • 个人比较喜欢这个 Arrays.stream(chains).iterator();
【解决方案2】:

您需要在迭代器方法的实现中返回接口Iterator 的实现。您还应该在类声明中指定迭代器的泛型类型。

@Override
public Iterator<DNAChain> iterator()
{
    return new Iterator<DNAChain>()
    {
        @Override
        public boolean hasNext() { return false; }

        @Override
        public DNAChain next() { return null; }

    };
}

编辑:实际上在您的情况下,您应该返回实验本身,因为它是实现迭代器的类......这很糟糕!创建一个实现您的 ExpIterator 的内部类。同样仅供参考,变量名称应按约定以小写字母开头(DNAChain[] 链)。

应该是这样的:

public class Experiment implements Iterable
{
    private DNAChain[] chains; // Chains found in the experiment
    private int counter; // next  chain  index

    public  Experiment () {}
    public  Experiment (int  n) { chains  = new DNAChain[n]; }

    public DNAChain[] getChains() { return chains; }
    public void setChains(DNAChain[] chains) { this.chains = chains; }

    public class ExpIteratorImpl implements ExpIterator
    {
        @Override
        public void setLevel(int n) { }

        @Override
        public boolean hasNext() { return counter < chains.length; }

        @Override
        public DNAChain next() { return chains[counter++]; }
    }

    @Override
    public Iterator iterator() { return new ExpIteratorImpl(); }
}

当您的实验完全设置后,检索迭代器以遍历您的 DNA 链。

【讨论】:

  • 你能举一个简单的例子来说明如何创建实现 ExpIterator 的内部类吗?
  • 我只是坚持下去。
  • @Michael,我在帖子中添加了一个示例。
猜你喜欢
  • 2021-08-10
  • 1970-01-01
  • 1970-01-01
  • 2022-09-27
  • 1970-01-01
  • 1970-01-01
  • 2018-12-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多