递归方法的StackOverflowError

时间:2015-03-01 18:34:44

标签: java recursion bukkit stack-overflow

使用递归方法时出现StackOverflowError。我正在构建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)收到错误,如果产生的玩家已有玩家,则会自行调用错误。

2 个答案:

答案 0 :(得分:1)

看起来s.hasPlayer()总是如此,如此:

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

spawnPlayer(Player)方法内执行,因此导致方法无限运行,导致StackOverflowError

要解决此问题,您可以在致电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...
   }
}

答案 1 :(得分:0)

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

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

注意!。

一般情况下,在我的世界中使用递归功能需要很多照顾:)一旦我写了一个将树变成日志但它最终在树叶上递归 - 爆炸非常壮观 - 一扫而空由于所有的活动,福雷斯特和杀死了我的客户。