如何修复此递归StackOverFlowException错误?

时间:2016-04-26 18:49:44

标签: java mysql recursion stack-overflow

所以我有一个存储在MySQL数据库中的朋友系统的数据,以及一种用于检索Java对象中的数据的API。

Java对象(MPlayer)包含用户名,在线状态,朋友(以“:”分隔的ID)之类的内容。 MPlayer对象将播放器的唯一ID作为构造函数。

数据在创建时和调用reload()方法时保存在对象中。这不是每次我想获得像用户名这样的东西时访问数据库。原因是我需要在循环中获取数据以显示在GUI上,我显然不希望每帧都下载数据。相反,我只是每6秒左右使用一次重载方法。

其中一个函数是getFriends()并返回一个MPlayer列表。创建MPlayer对象时存储该列表。问题是,当每个MPlayer朋友被创建时,它会为他们的朋友创建一个列表,这列表会为他们的朋友创建一个列表,最终会因递归而导致StackOverFlowException。

什么是避免错误的好方法?

有问题的代码:

MPlayer构造函数/加载方法:

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 个答案:

答案 0 :(得分:0)

显而易见的答案是&#34;在没有终止的情况下退出并退出#34;

您不希望在朋友列表中无限制关闭 - 但您想要做什么?只是朋友列表?在这种情况下,您可能需要一个单独的对象类型,例如&#34; FriendList&#34;。在创建它时,您只需列出好友ID;在专门访问之前,请不要加载朋友记录。

另一种方法是编码要激活的级别数,使其成为对象加载的参数。对于isntance,加载主MPlayer,深度为N = 2。对于您的主要朋友,加载到N-1的深度。当您点击0时,列出ID而不加载记录(如上所述)。

这会让你走向解决方案吗?