这是最佳实践问题。
我目前正在使用旧的Java代码。我看到很多Exception的子类只覆盖了构造函数。我不确定是否有任何像这样的子类化Exception的实际用法。我认为只是调用Exception构造函数并传入消息将同样有效,并且不会有很多子类。守则是责任。
答案 0 :(得分:11)
子类化的要点是您的代码可以区分不同类型的故障并以不同方式对待它们。如果您只是更改了消息,那么 human 可以在日志中区分它们,但这就是全部。
如果你看到的异常实际上没有被区别对待,但只是陷入了一个全能catch(Exception e)
那么也许有人对子类过于热心,但它通常对于干净地分离层次很有用。代码并确定哪些类应该处理哪种类型的问题。
例如,一种类型的异常可能表示超时,并且可能适合在短暂延迟后重试,而另一种类型的异常表示不可恢复的故障(可能是无效的查询)必须抛出到更高级别或可能向用户指示。
答案 1 :(得分:2)
要添加其他答案:
如果你扩展Exception
并抛出它,你就会宣布一个新的已检查异常。它必须在您的方法的throws子句中声明。你对来电者说:“这是一个不寻常的案例,你必须编码”。
我认为已检查的异常被过度使用。它们仅在调用者可以从问题中恢复的情况下才真正有用。我见过的绝大多数例外情况都是调用者无法合理期望从中恢复的类型。在这种情况下,您应该使用RuntimeException
后代,例如IllegalStateException
或IllegalArgumentException
,并让顶级错误处理来处理它。
答案 2 :(得分:1)
当你有一个子类时,你可以捕获它。您无法根据其消息选择性地捕获异常。
子类更具描述性且更易于使用:
throw new Exception("User does not exist " + userName);
与之相比:
throw new UserNotExistsException(userName);
后一个异常也可以有getUserName()
方法和字段,以便在捕获时提取重要信息。你不想解析异常消息,不是吗?
答案 3 :(得分:1)
这样做是为了更清晰,更准确地捕获异常。如果您的所有代码都抛出Exception
,那么您的异常处理代码必须如下所示:
try {
// ...
throw new Exception("configuration error");
// ...
throw new Exception("missing value error");
// etc.
} catch (Exception e) {
// do something
}
至少以不同方式处理不同类型的错误会很尴尬。更重要的是,这段代码将吞没所有异常,甚至是您没有预料到的异常,并且您没有编写特定的错误处理逻辑。另一方面,如果你写
try {
// ...
throw new ConfigurationException();
// ...
throw new MissingValueException();
// etc.
} catch (ConfigurationException e) {
System.err.println("error: bad configuration");
System.exit(1);
} catch (MissingValueException e) {
return DEFAULT_VALUE;
}
您将能够轻松,干净地处理各种错误,并且不必担心您的错误处理代码将在您不期望的情况下运行。
答案 4 :(得分:0)
子类化是要走的路。稍后在应用程序的生命周期中,您可能需要更改异常消息。谁知道它可能会显示在页面上,并且需要调整措辞。
将错误消息包装在自己的Exception子类中有助于维护干净的代码并轻松地针对给定的错误类别进行测试。