自定义未经检查的异常不会使抛出和调用方法返回

时间:2015-10-03 15:17:17

标签: java exception bukkit

我有一个问题,我无法在一个全新的项目上重现;它是在针对Spigot 1.8.8-R0.1构建的Bukkit插件上发生的。

我正在开发一个命令框架。 有两种类型的命令:只能由玩家运行的命令......

private Map<Command, PlayerCommand> playerCommands = new HashMap<>();
public interface PlayerCommand {
    void run(Player sender, String[] args);
}

......以及可能由控制台运行的那些。

private Map<Command, GlobalCommand> globalCommands = new HashMap<>();
public interface GlobalCommand {
    void run(CommandSender sender, String[] args);
}

要注册命令,我已经实现了3种方法:

  • 每个命令类型的2个公共方法,应将每个自定义执行程序添加到其特定的HashMap
public void registerCommand(String name, PlayerCommand executor) {
    Command command = registerCommand(name);
    // 2
    playerCommands.put(command, executor);
}
public void registerCommand(String name, GlobalCommand executor) {
    Command command = registerCommand(name);
    // 2'
    globalCommands.put(command, executor);
}
  • 他们共有的逻辑的私有方法,即将他们的Bukkit的CommandExecutor属性设置为当前实例(稍后将处理它们,将工作委托给从地图中获取的特定自定义执行程序) )。
private Command registerCommand(String name) {
    PluginCommand command = plugin.getCommand(name);
    if (command.getExecutor() == this) {
        throw new CommandAlreadyRegisteredException("The '" + name + "' command has been already registered");
    }
    // 1
    command.setExecutor(this);
    return command;
}

您可能已经注意到,客户端不应该多次注册相同的命令。

为了达到这个目的,我知道我可以要求已经包含命令的地图,但这将是两个操作,同时用==运算符检查执行程序(它必须是这个例子,不只是equals())只是一个。

所以,对于错误的情况,我决定抛出一个未经检查的异常:

public class CommandAlreadyRegisteredException extends RuntimeException {
    private static final long serialVersionUID = 1L;
    protected CommandAlreadyRegisteredException(String message) {
        super(message);
    }
}

这就是重点:我期望抛出异常将在抛出它的方法中返回,并在上层调用方法中返回。也就是说,第1,2和2点&#39;在这种情况下永远不应该执行。 但他们确实被执行了! 这怎么可能?你能重现吗?为什么会这样?

我知道我可以在私有方法中返回null,但是客户端不会知道已经注册的命令。

3 个答案:

答案 0 :(得分:1)

首次尝试注册命令:

  • 您从插件中获取命令。
  • 该命令没有执行程序,因此检查失败。
  • 然后设置执行者。

第二次尝试:

  • 您从插件中获取命令。 它与您第一次获得的命令相同。
  • 它仍然将this视为其执行者。检查通行证,抛出异常。

如果你想要的是阻止它被同一执行者注册两次,那么绝对不需要例外:

private Command registerCommand(String name) {
    PluginCommand command = plugin.getCommand(name);
    if (command.getExecutor() != this) {
        command.setExecutor(this);
    }
    return command;
}

答案 1 :(得分:0)

没有错误。

为了调试,我在抛出异常后添加了一些System.out.println()。 我正好打印那些断点。 没关系,因为这是第一次被允许注册,但出于某种原因,我认为它们是由第二次引起的...我不知道为什么。

答案 2 :(得分:-3)

您需要从Exception而不是RuntimeException扩展自定义异常类,然后才会对其进行检查,之后您可以在需要该异常的任何地方使用代码throw new YourException()被抛出。