5

このエラーを正しく説明する方法が本当にわかりません...

このメソッドをコントローラークラスに追加したときに始まりました。

public void loadPlayerComboBox() {
    try{
        final PreparedStatement collectPlayerNames = 
                ConnectionManager.getConnection().prepareStatement("SELECT "+PLAYER_NAME+"  FROM PLAYERS");
        final ResultSet playerNameResults = collectPlayerNames.executeQuery();
        while(playerNameResults.next()){
            IViewManager.Util.getInstance().getMyContainerPane().getMyPlayerManagerPane().getPlayerNameList()
            .add(playerNameResults.getString(PLAYER_NAME));
        }
    }catch(final SQLException e){
        System.out.println("SQLException. Reason: " + e.getMessage());
    }
}

そして、このメソッド(プログラムの起動時にクラスによって呼び出される)がなければ、エラーが発生しないことを確認しました。

私のエラー?Eclipseから実行すると、プログラムはフレームのトップバーの読み込みを開始しますが、実際のコンテンツは表示されません。

ここに画像の説明を入力してください

これに加えて、奇妙な溺れている空の箱があります。これは、複数のプロセスが起動されていることが原因であると私は信じています。

これは、getInstance()メソッドが相互に再帰的に呼び出したため、スタックオーバーフローが原因であると考えています。何らかの理由でスタックトレースを取り戻すことができず、現時点ではデバッグ画面が空白になっています。.logを確認しましたが、そのタイムスタンプに対応するエラーはありません。でも、どうやってお互いを呼ぶことができるのかわかりません。ViewManagerメソッドは次のとおりです。

static class Util {
    static private IViewManager viewManager = null;
    static public synchronized IViewManager getInstance() {
            if (viewManager == null) {
                    viewManager = new ViewManager();
            }
            return viewManager;
    }
}

そしてコンストラクター:

public ViewManager(){
    super("Tony Larp DB Manager");
    this.setVisible(true);
    this.setDefaultCloseOperation(3);
    myContainerPane = new ContainerPane();
    myContentMenu = new ContentMenu();
    IController.Util.getInstance();
    IPlayerCharacterManager.Util.getInstance();
    this.setJMenuBar(myContentMenu);
    this.getContentPane().add(myContainerPane);
    this.pack();        
}

IController.Util.getInstance()メソッドは、呼び出すクラスとオブジェクトの名前が異なることを除いて、同じです。ダブルチェックロックにより、ランチャーのIViewManager.getInstance()の最初のインスタンスがnullポインターを返します。これは、同期されたブロックの開始時です。

明確にするために、プログラムはIViewManager.Util.getInstance()ランチャーで最初に呼び出し、次にIController.Util.getInstance()上記のコンストラクターで初めて呼び出します。その後、それへのすべての呼び出しはインスタンスを返すだけです。

この種のエラーの原因は何ですか?どうすれば修正を開始できますか?

4

2 に答える 2

1

これが難しいと思われないことを願っています:あなたのコードはひどく構造化されています:-/

私はあなたにあなたの質問に対する解決策を与えることはできません。たぶん、あなたの完全なコードを見ることができれば、私はそうすることができます。しかし、私はあなたにもっと一般的な助けを与えたいと思います。多分それならあなたはあなた自身であなたの問題を解決することができるでしょう。

構造を単純化してクリーンアップするようにしてください。ここにいくつかの提案があります:

UIにシングルトンが必要な場合は、私の意見では問題ありません。一般的にシングルトンは「悪臭」かもしれませんが、常に注意深く見る必要があります。あなたの場合、怠惰な初期化、同期などを取り除くことができます。

単に書く

static class Util {
    public static final IViewManager viewManager = new ViewManager();
}

UIにViewManagerを1つだけ必要とする場合(妥当なサウンドで)。

そうすれば、もう電話する必要はあり... .Util.getInstance()ません。単に書くUtil.viewManager

関心の分離を達成するように努める必要があります。1つのクラスに1つのことだけをさせましょう。ViewManagerはビューを管理します。他には何もありません。ビュークラスは、ダイアログのレイアウトを担当する場合があります。ただし、ビュークラスは、データベースにクエリを実行してコンボボックスを埋める方法を知っている必要はありません。ビュークラスはSQLを知っている必要があります。また、ビュークラスは 、他のクラスのすべてのタスクであるMyPlayerManagerPaneへの奇妙な方法も知っています。

ゲームやプレーヤーのデータが必要な場合は、GameRepositoryのようなものを質問したいと思うかもしれません。あなたはそのようなクラスを誘発することができます。次に、GameRepositoryクラスのインスタンスをビューに指定し、ビュー内で次のように言うことができます。

...
ComboBoxModel playersModel = createPlayersModel(gameRepository.getPlayers());
playersCombobox.setModel(playersModel);
...

このようにして、比較的小さなクラスを取得します。このようなクラスは、それ自体で簡単にテストできます。また、開発中のある時点で奇妙な動作が発生した場合は、その理由をすぐに見つけることができます。

あなたがポイントを得ることを願っています;-)

于 2012-07-31T15:10:30.010 に答える
0

この種の動作は、ある種の無限ループがあることを示しています。スレッドを横断した場所もあります(スレッド内の一方のメソッドがもう一方のメソッドを呼び出し、もう一方のメソッドが最初のメソッドを呼び出します)。

どちらも構築を終了しないため、シングルトンには呼び出すインスタンスがありません。代わりに、彼らはお互いを無限にインスタンス化しようとし続けます。戻って、シングルトンコードスレッドがどれほど分離しているかを再考してください。

于 2012-09-03T12:16:40.110 に答える