2012-06-24 122 views
1

我有一堆表格视图,其中有代码重复。他们曾经直接继承AbstractView类。然后我让它们继承了AbstractListView(它将继承AbstractView),这将成为保存这些表的所有公共属性的新类。多级继承和foreach Java循环

自从我做了改变,此环奇怪的行为:

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类型的。

UPDATE 我设法找到它仅仅涉及改变环路解决方法:

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

我想知道为什么,虽然在foreach循环风格是让我头疼。

+0

如何定义'AbstractViewPanel'? – nhahtdh

+0

谁? arrayList是Java中的一个常规实现,我还没有实现任何自定义迭代器模式。虽然现在我怀疑线程问题,但循环并没有结束,它从未到达函数的末尾。 –

+0

在'registeredViews'声明中指定了什么类型的参数。 – trashgod

回答

1

仅供参考,我已经创建了您的设计的骨架sscceList<E> implements Iterable<E>,所以没有先验原因你的foreach应该失败。这里有一些事情要检查:

  • 验证GUI对象构造,并在event dispatch thread操纵

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

  • 由于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 { 
    } 
} 
+0

我会研究所有这些,你的答案非常完整,所以我会接受它。当我找到这个的根本原因时,我会进行更新。 –

1

我相信你modelPropertyChange改变registeredViews列表。

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

但是,当你运行的每个循环,如果modelPropertyChange改变列表可能你的迭代器给你一些问题。

+0

我一开始认为,但是在这种情况下你会不会看到并发修改异常? –

+0

也许,但这是我在这一刻最可能的解决方案,并且很容易证明:更改foreach循环内容,删除'view.modelPropertyChange(evt);'并写入'System.out.println(“view:” + view);'。它工作,然后我的回答是真实的! – dash1e

+0

我试过了,它的行为和你提到的一样。但是我的modelPropertyChange不会改变registeredViews列表,我查看了调用层次结构,并且我只是最初添加了一些东西并对其进行了循环。 –