java - Java 多级继承和 foreach 循环

标签 java

我有一堆 TableView ,其中有重复的代码。他们以前都是直接继承AbstractView类。然后我让它们继承 AbstractListView(反过来又继承自 AbstractView),这将是保存这些表的所有公共(public)属性的新类。

自从我进行了更改后,这个循环的行为就很奇怪:

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

这是 arrayList:registeredViews:

private ArrayList<AbstractViewPanel> registeredViews;

我已经运行了调试器,并且 RegisteredViews arrayList 包含所有 View ,包括 TableView 。由于某种原因,它停在集合中最后一个直接继承的 View 处并完全跳过它们。

我所有的 View 都用来直接继承:

public class someView extends AbstractViewPanel

自从我改变后,一些观点是这样的:

public class someOtherView extends AbstractListView

这是 AbstractListView:

public abstract class AbstractListView extends AbstractViewPanel

这是抽象 View 面板

public abstract class AbstractViewPanel extends JPanel {


public abstract void modelPropertyChange(PropertyChangeEvent evt);

}

循环根本不会遍历继承 AbstractListView 的任何内容,但我假设最终的所有 View 都是 AbstractView 类型。

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

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

我想知道为什么 foreach 样式循环让我头疼。

最佳答案

作为引用,我创建了一个骨架 sscce您的设计。 List<E>实现Iterable<E> ,因此您的 foreach 没有先验理由。应该失败。以下是一些需要检查的事项:

  • 验证 GUI 对象是否仅在 event dispatch thread 上构建和操作。 .

  • 验证您没有忽略 ClassCastExceptionSomeOtherView 的实例时检索自List .

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

  • 附录:在这种情况下您不会看到并发修改异常吗?

    不, ConcurrentModificationException “并不总是表明对象已被不同线程同时修改。”如果“列表已 structurally modified”位于迭代器之外,则尽最大努力抛出异常。更有可能的是,失败的迭代器是在添加一些 View 之后但在添加其他 View 之前获得的。如果列表是在初始线程上构建并在 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 {
    }
}

关于java - Java 多级继承和 foreach 循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11174602/

相关文章:

java - 无需 Hibernate Envers 即可审计 java 实体

java - 在 Java 中将文件读入 byte[] 数组的优雅方法

java - Logback 附加程序和 Postfix

java - 如何从返回android应用程序中的对象的android应用程序使用asmx web服务?

java - 身份验证后重定向到 protected 页面

java - 在内部存储中存储可绘制对象或位图

java - ComboBox - 打印出所选项目

java - Hibernate 多对多映射和 cascade=delete

java - 如何在 Java 中对 ZipOutputStream 进行单元测试

java - 如何以编程方式将 JasperViewer 保存到文件/流?