如何修复此递归 StackOverFlowException 错误?
How can I fix this recursive StackOverFlowException error?
所以我有一种朋友系统的数据存储在 MySQL 数据库中,还有一种 API 用于检索 Java 对象中的数据。
Java 对象 (MPlayer) 包含诸如用户名、在线状态、好友(ID 以“:”分隔)之类的内容。 MPlayer 对象将播放器的唯一 ID 作为构造函数。
数据在创建时和调用reload()方法时保存在对象中。这不是每次我想获取用户名之类的信息时都访问数据库。这样做的原因是我需要循环获取数据以显示在 GUI 上,而我显然不想每一帧都下载数据。相反,我只是每 6 秒左右使用一次 reload 方法。
函数之一是 getFriends() 和 returns MPlayer 列表。该列表在创建 MPlayer 对象时存储。问题是,当每个 MPlayer 好友被创建时,它会为他们的好友创建一个列表,而这个列表又会为他们的好友创建一个列表,由于递归而导致 WhosebugException。
避免错误的好的解决方案是什么?
有问题的代码:
MPlayer constructor/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;
}
显而易见的答案是 "quit doing it recursively with no termination"。
您不希望在朋友列表上无限关闭 -- 但您想要做什么?只是好友列表?在那种情况下,您可能需要一个单独的对象类型,例如 "FriendList"。创建这个时,您只需列出朋友 ID;在特定访问之前不要加载好友记录。
另一种方法是编写要激活的级别数,使其成为对象加载的参数。例如,加载深度为 N=2 的主 MPlayer。对于你主要的每个朋友,加载到 N-1 的深度。当你打0时,列出ID而不加载记录(如上)。
这是否促使您找到解决方案?
所以我有一种朋友系统的数据存储在 MySQL 数据库中,还有一种 API 用于检索 Java 对象中的数据。
Java 对象 (MPlayer) 包含诸如用户名、在线状态、好友(ID 以“:”分隔)之类的内容。 MPlayer 对象将播放器的唯一 ID 作为构造函数。
数据在创建时和调用reload()方法时保存在对象中。这不是每次我想获取用户名之类的信息时都访问数据库。这样做的原因是我需要循环获取数据以显示在 GUI 上,而我显然不想每一帧都下载数据。相反,我只是每 6 秒左右使用一次 reload 方法。
函数之一是 getFriends() 和 returns MPlayer 列表。该列表在创建 MPlayer 对象时存储。问题是,当每个 MPlayer 好友被创建时,它会为他们的好友创建一个列表,而这个列表又会为他们的好友创建一个列表,由于递归而导致 WhosebugException。
避免错误的好的解决方案是什么?
有问题的代码:
MPlayer constructor/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;
}
显而易见的答案是 "quit doing it recursively with no termination"。
您不希望在朋友列表上无限关闭 -- 但您想要做什么?只是好友列表?在那种情况下,您可能需要一个单独的对象类型,例如 "FriendList"。创建这个时,您只需列出朋友 ID;在特定访问之前不要加载好友记录。
另一种方法是编写要激活的级别数,使其成为对象加载的参数。例如,加载深度为 N=2 的主 MPlayer。对于你主要的每个朋友,加载到 N-1 的深度。当你打0时,列出ID而不加载记录(如上)。
这是否促使您找到解决方案?