2016-04-26 7 views
0

私は、MySQLデータベースに格納されている一種の友人システムのデータと、Javaオブジェクトのデータを取り出すための一種のAPIを持っています。この再帰的なStackOverFlowExceptionエラーを修正するにはどうすればよいですか?

Javaオブジェクト(MPlayer)には、ユーザー名、オンラインステータス、フレンド(「:」で区切られたID)のようなものが含まれています。 MPlayerオブジェクトは、コンストラクタとしてプレーヤのユニークIDを取得します。

データは、作成時およびreload()メソッドの呼び出し時にオブジェクトに保存されます。これは、ユーザー名のようなものを取得するたびにデータベースにアクセスするのではなく、これです。その理由は、GUIに表示するためにループ内のデータを取得する必要があり、明らかにフレームごとにデータをダウンロードしたくないからです。代わりに、私はちょうど6秒ほどごとにreloadメソッドを使用します。

関数の1つはgetFriends()であり、MPlayerのリストを返します。このリストは、MPlayerオブジェクトの作成時に格納されます。問題は、MPlayerの各友達が作成されるときに、友人のためのリストを作成し、友達のリストを作成し、再帰のためにStackOverFlowExceptionに終わることです。

エラーを回避するにはどうすればよい解決策でしょうか?問題の

コード:

MPlayerのコンストラクタ/ loadメソッド:

public MPlayer(String player){ 
    this.uuid = player; 
    try { 
     st.setString(1, uuid); 
    } catch (SQLException e) { 

     e.printStackTrace(); 
    } 
    this.reload(); 
} 

public void reload(){ 
    try { 
     ResultSet set = st.executeQuery(); 
     if(set.next()){ 
      if(set.getString("server").equals("none")){ 
       isConnected = false; 
      }else{ 
       isConnected = true; 
      } 
     } 
    } catch (SQLException e) { 

     e.printStackTrace(); 
    } 

    try { 
     ResultSet set = st.executeQuery(); 
     if(set.next()){ 
      this.serverIP = set.getString("server"); 
     } 
    } catch (SQLException e) { 

     e.printStackTrace(); 
    } 



    try { 

     ResultSet set = st.executeQuery(); 
     if(set.next()){ 
      this.username = set.getString("username"); 
     } 
    } catch (SQLException e) { 

     e.printStackTrace(); 
    } 


    try { 
     ResultSet get = st.executeQuery(); 
     if(get.next()){ 
      this.online = get.getBoolean("status"); 
     } 
    } catch (SQLException e) { 

     e.printStackTrace(); 
    } 
    try { 


     List<MPlayer> list = new ArrayList<MPlayer>(); 
     ResultSet get = st.executeQuery(); 
     if(get.next()){ 
      for(String str : get.getString("friends").split(":")){ 
       if(!str.equalsIgnoreCase("none")){ 
        MPlayer player = new MPlayer(str); 
        if(player.isOnline()){ 
         list.add(0,player); 
        }else{ 
         list.add(player); 
        } 
       } 
      } 

     } 
     this.friends = list; 
    } catch (SQLException e) { 

     e.printStackTrace(); 
    } 


    this.settings = new Settings(this); 


    PreparedStatement state = Main.getPreparedStatement("SELECT * FROM updates WHERE uuid=?"); 
    try { 
     state.setString(1, this.getUUID()); 
     ResultSet set2 = state.executeQuery(); 
     List<StatusUpdate> updates = new ArrayList<StatusUpdate>(); 

     while(set2.next()){ 
      updates.add(new StatusUpdate(set2.getInt(1))); 
     } 
      Collections.sort(updates, new Comparator<StatusUpdate>() { 
       @Override 
       public int compare(StatusUpdate r1, StatusUpdate r2) { 

        return -1 * r1.getDate().compareTo(r2.getDate()); 
       } 
      }); 

     this.updates = updates; 
    } catch (SQLException e) { 

     e.printStackTrace(); 
    } 


    List<StatusUpdate> updates = new ArrayList<StatusUpdate>(); 

    for(MPlayer p : this.getFriends()){ 
     updates.addAll(p.getStatusUpdates()); 

    } 
    updates.addAll(this.getStatusUpdates()); 
    Collections.sort(updates, new Comparator<StatusUpdate>() { 
     public int compare(StatusUpdate m1, StatusUpdate m2) { 

      return -1 * m1.getDate().compareTo(m2.getDate()); 
     } 
    }); 
    this.timeline = updates; 



} 
+1

あなたのコードと正確なエラーを投稿してください。 [SOに関する質問](http://stackoverflow.com/help/how-to-ask)。 – Dresden

+0

ここでの問題は、 'reload'関数から' MPlayer player = new MPlayer(str) 'を呼び出すことですが、' MPlayer'のコンストラクタでは 'this.reload();'も呼び出すでしょう'MPlayer player = new MPlayer(str);'を呼び出すと、ループは無限になります - 最初のステップはあなたのコードをリファクタリングすることです - あなたの 'reload'関数がそうしていることは良い考えではありません... – ishmaelMakitla

答えて

0

明白な答えは "ノー終了に再帰的にそれをやって終了" されます。

友だちのリストに無制限の閉鎖を望んでいませんが、何がになるのですか?あなたは欲しいですか?友達のリストだけ?その場合は、「FriendList」などの別のオブジェクトタイプが必要になることがあります。これを作成するには、単に友だちIDを一覧表示するだけです。特にアクセスされるまで友達のレコードを読み込まないでください。

もう1つの方法は、アクティブ化するレベルの数をコード化し、これをオブジェクトのロードのパラメータにすることです。 isntanceのために、N = 2の深さでプライマリMPlayerを読み込みます。あなたのプライマリの友達ごとに、N-1の深さまでロードしてください。 0を押すと、上記のようにレコードをロードせずにIDを一覧表示します。

解決策に向かって進むのですか?

+0

私は参照してください。読み込み専用プレーヤーオブジェクトの並べ替え?ありがとう、あなたは「あなたが間違ってやっている、コードをやり直して後で戻ってくる」人がいなかった数少ない例の一つです。 –

+0

あなたは大歓迎です。はい、読み取り専用はそれを見るための1つの方法です。何よりも、制限のない再帰を解除するには、派生のケースをプライマリから分離するだけで済みます。 – Prune

+0

あなたのコードは「自然な方法」とは思えないと私は他の人に同意しますが、あなたの問題空間が私たちよりも優れていると思います。 :-)例えば、あなたのアプローチはあなたがまだ実装していない機能をうまくサポートするかもしれません。 – Prune

関連する問題