抛出 Exception 和抛出 NullPointerException 等特定异常的区别

Difference between throwing Exception and throwing a specific Exception such as NullPointerException

我想知道只抛出 Exception 和抛出特定异常(例如 NullPointer Exception.

之间有什么区别

据我目前所知,Exception 应该能够捕获任何类型的异常,因为使用特定的异常预计只能抛出该异常类型。

示例:

void test(String testString) throws Exception;

void test(String testString) throws NullPointerException;

如果这对我来说是正确的,那么总是抛出异常并且从不命名特定异常是有意义的。我在这里错过了一些重要的东西吗?它至少会影响性能吗?很多人都在抛出和捕获异常之间寻找,但没有人问这个非常基本的问题。

除了Exception,我没有看到抛出任何异常的好处。

最佳做法是抛出特定异常,而不是一般异常。这是因为调用者可能希望以不同的方式处理异常,例如在 WebApi 中,您可能希望 return 对 ArgumentNullException 的错误请求响应 (400),但您可能希望 return 不同的其他类型异常的结果。例如,您实际上可能会抛出一个自定义 NotFoundException,然后控制器会捕获它并 return 一个 Not Found 响应 (404)。 基本上,如果你抛出特定的异常,你就允许消费者代码按照他们想要的方式处理不同的异常场景。

你提到的 NullPointerException 是常规 Exception 的一个很好的例子,因为它是 RuntimeException 的子类。 RuntimeException(的子类)的任何抛出都不必被捕获或声明。

任何其他(=不是 RuntimeException 的子类)异常必须在您的代码中通过 try/catch 块或 throws 声明来处理。否则,您的代码甚至无法编译!这迫使您作为开发人员处理可能弹出的错误。

至于为什么使用不同的异常类型有用,请考虑以下使用多个 catch 语句的简单示例:

void doDBStuff(){
  try {
    performStatement(someStatement);
  } catch(SQLException e){
    //invalid SQL syntax, something is broken
  } catch(AuthenticationException e){
    //invalid user credentials for the db, inform the user to change these values
  }

在此示例中,两个不同的异常最终出现在两个不同的 catch 块中,这使您可以以不同的方式处理这些错误。

至少有两个原因会导致您想要抛出特定类型的异常:

  1. 如果程序因异常而失败,您将获得更多信息来确定问题所在。比较看到 ExceptionFileNotFoundException。后者显然为您提供了更多信息。
  2. 在某些情况下,代码会想要捕获某些类型的异常。例如,在使用串行端口时,您可能希望以不同于 NullReferenceException.
  3. 的方式捕获和处理 TimeoutException

首先,Exception 是每个 Exception 的基类型。就像 object 代表一切。

通过抛出一个特定的 Exception,您可以向消费者提供更多关于发生的事情的信息。 想象一下你得到一个没有消息的普通 Exception 的场景,消费者丢失了。例如,当框架抛出 NullReferenceException 时,您就会意识到一个事实,即您的一个对象没有它试图访问的引用。

这是链接异常并利用它们的类型的方法:

try
{
   throw new NotImplementedException();
}
catch(NullReferenceException ex)
{
   // Logic for NullReference exception if needed.
}
catch(NotImplementedException ex)
{
   // This will be executed.
}
catch(Exception ex)
{
   // Will catch every exception.
}