多级继承和foreach Java循环

时间:2012-06-24 02:44:21

标签: java

我有一堆表视图,其中包含重复的代码。他们曾经直接继承AbstractView类。所以我让他们继承了AbstractListView(这将继承自AbstractView),这将是包含这些表的所有常见属性的新类。

由于我做了这个改变,这个循环表现得很奇怪:

for (AbstractViewPanel view : registeredViews) {
        view.modelPropertyChange(evt);
}

这是arrayList:registeredViews:

private ArrayList<AbstractViewPanel> registeredViews;

我运行调试器并且registeredViews arrayList具有包括表格的所有视图。由于某种原因,它会停留在集合中最后一个直接继承的视图中,并完全跳过它们。

我的所有观点都用于直接继承:

public class someView extends AbstractViewPanel

现在,由于我的更改,一些观点是这样的:

public class someOtherView extends AbstractListView

这是AbstractListView:

public abstract class AbstractListView extends AbstractViewPanel

这是AbstractViewPanel

public abstract class AbstractViewPanel extends JPanel {


public abstract void modelPropertyChange(PropertyChangeEvent evt);

}

循环根本不会覆盖任何继承AbstractListView的东西,但我会假设最后的所有视图都是AbstractView类型。

更新 我设法找到一个解决方法,它只涉及更改循环:

for (int i = 0; i < registeredViews.size(); i++) 
{
        registeredViews.get(i).modelPropertyChange(evt);
}

我想知道为什么foreach风格循环让我感到头痛。

2 个答案:

答案 0 :(得分:1)

作为参考,我已经创建了你设计的骨架sscceList<E>实施Iterable<E>,因此foreach失败的原因不存在先验原因。以下是一些要检查的事项:

  • 验证event dispatch thread上是否只构建和操作GUI对象

  • 当从ClassCastException检索SomeOtherView的实例时,确认您没有忽略List

  • 由于List是异质的,请参阅Bloch, Effective Java 2nd ed.,第29项:考虑类型安全的异构容器。“提到的模式为here

  • 附录:在这种情况下你不会看到并发修改例外吗?

    不,ConcurrentModificationException“并不总是表明某个对象已被不同的线程同时修改。”如果“列表在迭代器之外已经structurally modified”,则会尽最大努力抛出异常。更有可能的是,失败的迭代器是在添加一些视图之后获得的,但之前添加其他视图。如果列表是在初始线程上构建并在EDT上迭代的话,这可能会意外发生。

SSCCE:

import java.awt.EventQueue;
import java.awt.GridLayout;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

public class Test {

    private List<AbstractViewPanel> registeredViews;

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                new Test().init();
            }
        });
    }

    private void init() {
        JFrame f = new JFrame("Test");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setLayout(new GridLayout(0, 1));

        registeredViews = new ArrayList<AbstractViewPanel>();
        for (int i = 0; i < 2; i++) {
            registeredViews.add(new SomeView());
            registeredViews.add(new SomeOtherView());
        }
        for (AbstractViewPanel view : registeredViews) {
            f.add(view);
        }

        f.pack();
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }

    abstract class AbstractViewPanel extends JPanel {

        public AbstractViewPanel() {
            add(new JLabel(getClass().toString()));
        }
    }

    abstract class AbstractListView extends AbstractViewPanel {
    }

    class SomeView extends AbstractViewPanel {
    }

    class SomeOtherView extends AbstractListView {
    }
}

答案 1 :(得分:1)

我相信您的modelPropertyChange会更改registeredViews列表。

因此,当您使用计数器i运行循环时,循环将限制为循环开始时列表的大小。

但是当你使用for循环运行时,如果modelPropertyChange更改了列表,那么你的迭代器可能会给你一些问题。