1

コードが重複しているテーブルビューがたくさんありました。以前は、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スタイルのループがなぜ私に頭痛の種を与えていたのか知​​りたいのですが。

4

2 に答える 2

1

参考までに、あなたのデザインのスケルトンsscceを作成しました。List<E>を実装Iterable<E>しているので、失敗する必要があるという先験的な理由foreachはありません。確認すべき点がいくつかあります。

  • GUIオブジェクトが、イベントディスパッチスレッドでのみ構築および操作されることを確認します。

  • ClassCastExceptionのインスタンスが SomeOtherViewから取得されるときに、を見逃していないことを確認しますList

  • Listは異種であるため、Bloch、Effective Java2ndedを参照しください、アイテム29:タイプセーフな異種コンテナを検討してください。」パターンはここに記載されています。

  • 補遺:その場合、同時変更の例外は発生しませんか?

    いいえ、 「オブジェクトがのスレッドConcurrentModificationExceptionによって同時に変更されたことを常に示しているわけではありません。」例外は、イテレータの外部で「リストが構造的に変更された」場合に、ベストエフォートベースでスローされます。失敗したイテレータは、一部のビューを追加した後、他のビューを追加するに取得された可能性があります。これは、リストが最初のスレッドで作成され、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 {
    }
}
于 2012-06-24T04:02:03.587 に答える
1

私はあなたがリストをmodelPropertyChange変えると信じていますregisteredViews

したがって、カウンターを使用してループを実行すると、iループはループの開始時のリストのサイズに制限されます。

ただし、for eachループを使用して実行する場合modelPropertyChange、リストを変更すると、イテレータで問題が発生する可能性があります。

于 2012-06-24T04:06:22.687 に答える