递归方法的 StackOverflowError

StackOverflowError on recursive method

我在使用递归方法时遇到 WhosebugError。我在 Spigot API.

之上构建

这是我的方法:

private Location spawnPlayer(Player p) {
    int r = new Random().nextInt(ServerManager.getInstance().getServer(p).getSpawns().size());
    final Spawn s = ServerManager.getInstance().getServer(p).getSpawns().get(r);

    if (s.hasPlayer()) {
        spawnPlayer(p);
    } else {
        s.setPlayer(p);

        Bukkit.getServer().getScheduler().scheduleSyncRepeatingTask(Arsenal.p, new Runnable() {
            public void run() {
                spawnClear--;

                if (spawnClear == 0) {
                    s.setPlayer(null);
                }
            }
        }, 0L, 20L);
    }
    return s.getLocation();
}

我在 spawnPlayer(p) 收到错误,如果 spawn 已经有玩家,它会自行调用。

看起来 s.hasPlayer() 总是正确的,因此:

if(s.hasPlayer()){
    spawnPlayer(p);
}

spawnPlayer(Player) 方法内部执行,因此导致该方法无限地 运行,导致 WhosebugError.

要解决此问题,您可以在调用 spawnPlayer(p):

之前等待
if(s.hasPlayer()){
    long timeToWait = 20L;//set the time to wait to 20 ticks (1 second)
    Bukkit.getServer().getScheduler().runTaskLater(Arsenal.p, new Runnable(){
        public void run(){
            spawnPlayer(p);
        }
    },timeToWait);
}

因此,您的代码可能如下所示:

private Location spawnPlayer(Player p) {
    int r = new Random().nextInt(ServerManager.getInstance().getServer(p).getSpawns().size());
    final Spawn s = ServerManager.getInstance().getServer(p).getSpawns().get(r);

    if(s.hasPlayer()){
        long timeToWait = 20L;//set the time to wait to 20 ticks (1 second)
        Bukkit.getServer().getScheduler().runTaskLater(Arsenal.p, new Runnable(){
            public void run(){
                spawnPlayer(p);
            }
         },timeToWait);
    }
    else{
        s.setPlayer(p);

        Bukkit.getServer().getScheduler().scheduleSyncRepeatingTask(Arsenal.p, new Runnable() {
            public void run() {
                spawnClear--;

                if (spawnClear == 0) {
                    s.setPlayer(null);
                }
            }
        }, 0L, 20L);
    }
    return s.getLocation();
}

另一个修复方法是使 s.hasPlayer() 不总是正确的,例如,通过使用 ArrayList 来确保玩家尚未生成:

List<String> spawned = new ArrayList<String>();

private Location spawnPlayer(Player p){
   int r = new Random().nextInt(ServerManager.getInstance().getServer(p).getSpawns().size());
   final Spawn s = ServerManager.getInstance().getServer(p).getSpawns().get(r);

   if(s.hasPlayer() && !spawned.contains(p.getName()){
      spawned.add(p.getName());
      spawnPlayer(p);
   }
   else{
     //the rest of your code...
   }
}

我不确定,但从逻辑上讲我认为你想要:

if (!s.hasPlayer()) {
    spawnPlayer(p);

注意!.

但总的来说,在 minecraft 中使用递归函数时要格外小心 :) 有一次我写了一个将树变成原木的函数,但它最终在树叶上递归——爆炸非常壮观——消失了整个阿甘,因为 activity.

杀了我的客户