我有一堆 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 上构建和操作。 .
验证您没有忽略
ClassCastException
当SomeOtherView
的实例时检索自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/