抛出 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 块中,这使您可以以不同的方式处理这些错误。
至少有两个原因会导致您想要抛出特定类型的异常:
- 如果程序因异常而失败,您将获得更多信息来确定问题所在。比较看到
Exception
和 FileNotFoundException
。后者显然为您提供了更多信息。
- 在某些情况下,代码会想要捕获某些类型的异常。例如,在使用串行端口时,您可能希望以不同于
NullReferenceException
. 的方式捕获和处理 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.
}
我想知道只抛出 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 块中,这使您可以以不同的方式处理这些错误。
至少有两个原因会导致您想要抛出特定类型的异常:
- 如果程序因异常而失败,您将获得更多信息来确定问题所在。比较看到
Exception
和FileNotFoundException
。后者显然为您提供了更多信息。 - 在某些情况下,代码会想要捕获某些类型的异常。例如,在使用串行端口时,您可能希望以不同于
NullReferenceException
. 的方式捕获和处理
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.
}