Java 自定义未检查异常不存在';t使抛出和调用方方法返回

Java 自定义未检查异常不存在';t使抛出和调用方方法返回,java,exception,bukkit,Java,Exception,Bukkit,我有一个问题,我无法复制一个全新的项目;这发生在Bukkit插件上,它是根据Spigot 1.8.8-R0.1构建的 我正在开发一个命令框架。 有两种类型的命令:只能由玩家运行的命令 private Map<Command, PlayerCommand> playerCommands = new HashMap<>(); …以及可能由控制台运行的 private Map<Command, GlobalCommand> globalCommands = new

我有一个问题,我无法复制一个全新的项目;这发生在Bukkit插件上,它是根据Spigot 1.8.8-R0.1构建的

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

private Map<Command, PlayerCommand> playerCommands = new HashMap<>();
…以及可能由控制台运行的

private Map<Command, GlobalCommand> globalCommands = new HashMap<>();
为了注册该命令,我实现了3种方法:

  • 每个命令类型有2个公共方法,它们应该将每个自定义执行器添加到其特定的
    HashMap
  • 1个专用方法,用于它们共同的逻辑,即将它们的Bukkit的
    CommandExecutor
    属性设置为当前实例(稍后将处理它们,将工作委托给从映射中获取的特定自定义执行器)
正如您可能已经注意到的,客户端不应该能够多次注册同一命令

为了实现这一点,我知道我可以要求映射已经包含该命令,但这将是两个操作,而使用
==
操作符检查执行器(必须是这个实例,而不仅仅是
equals()
)只是一个

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

public class CommandAlreadyRegisteredException extends RuntimeException {
    private static final long serialVersionUID = 1L;
    protected CommandAlreadyRegisteredException(String message) {
        super(message);
    }
}
private Command registerCommand(String name) {
    PluginCommand command = plugin.getCommand(name);
    if (command.getExecutor() != this) {
        command.setExecutor(this);
    }
    return command;
}
关键是:我希望抛出异常会在抛出异常的方法中返回,在上面的调用方方法中返回。也就是说,在这种情况下,第1点、第2点和第2点’不应执行。 但他们确实会被处决 这怎么可能?你能复制它吗?为什么会发生这种情况


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

您需要从
exception
扩展自定义异常类,而不是
RuntimeException
,因为这样会被检查,然后您可以使用代码
抛出新的异常()
需要抛出该异常的任何地方。

您需要从
exception
而不是
RuntimeException
扩展您的自定义异常类,然后将对其进行检查,然后可以使用代码
抛出新的YourException()
需要抛出该异常的任何位置。

首先尝试注册命令:

  • 您可以从插件获取命令
  • 该命令没有执行器,因此检查失败
  • 然后你设定遗嘱执行人
第二次尝试:

  • 您可以从插件获取命令它与您第一次得到的命令是同一个对象。
  • 它仍然将此视为其执行者。检查通过,抛出异常
如果您只想阻止它被同一执行人注册两次,那么绝对不需要例外:

public class CommandAlreadyRegisteredException extends RuntimeException {
    private static final long serialVersionUID = 1L;
    protected CommandAlreadyRegisteredException(String message) {
        super(message);
    }
}
private Command registerCommand(String name) {
    PluginCommand command = plugin.getCommand(name);
    if (command.getExecutor() != this) {
        command.setExecutor(this);
    }
    return command;
}

首次尝试注册命令:

  • 您可以从插件获取命令
  • 该命令没有执行器,因此检查失败
  • 然后你设定遗嘱执行人
第二次尝试:

  • 您可以从插件获取命令它与您第一次得到的命令是同一个对象。
  • 它仍然将此视为其执行者。检查通过,抛出异常
如果您只想阻止它被同一执行人注册两次,那么绝对不需要例外:

public class CommandAlreadyRegisteredException extends RuntimeException {
    private static final long serialVersionUID = 1L;
    protected CommandAlreadyRegisteredException(String message) {
        super(message);
    }
}
private Command registerCommand(String name) {
    PluginCommand command = plugin.getCommand(name);
    if (command.getExecutor() != this) {
        command.setExecutor(this);
    }
    return command;
}
没有bug

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

没有错误

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


我不想每次需要注册命令时都使用try-catch块。你是说未检查的异常不会阻止代码执行吗?所有异常都能够阻止程序的进一步执行。但是要抛出自定义异常,您必须显式地这样做,因为Java运行时无法知道您希望何时抛出异常,因此您必须使用我在代码中没有看到的throw关键字。从Exception类进行扩展更自然,因为这样更安全,因为异常将被检查,而RuntimeException的子类在第二个代码块第21行未被检查。这与是否检查异常无关,但是为什么运行时选择不让抛出的未经检查的异常阻止执行。很抱歉,我现在意识到您实际上已经显式抛出了异常。你检查过情况是否真的通过了吗。我的意思是,如果条件失败或通过,我不想每次需要注册命令时都使用try-catch块。你是说未检查的异常不会阻止代码执行吗?所有异常都能够阻止程序的进一步执行。但是要抛出自定义异常,您必须显式地这样做,因为Java运行时无法知道您希望何时抛出异常,因此您必须使用我在代码中没有看到的throw关键字。从Exception类进行扩展更自然,因为这样更安全,因为异常将被检查,而RuntimeException的子类在第二个代码块第21行被取消检查。这不是是否检查异常的问题,而是为什么运行时选择不让抛出的异常取消检查
private Command registerCommand(String name) {
    PluginCommand command = plugin.getCommand(name);
    if (command.getExecutor() != this) {
        command.setExecutor(this);
    }
    return command;
}