引发异常和引发特定异常(如NullPointerException)之间的区别

引发异常和引发特定异常(如NullPointerException)之间的区别,exception,exception-handling,language-agnostic,throws,Exception,Exception Handling,Language Agnostic,Throws,我想知道仅仅抛出异常和抛出特定异常(如NullPointer异常)之间有什么区别 据我目前所知,异常应该能够捕获任何类型的异常,因为使用特定异常时,只能抛出该异常类型 示例: void test(String testString) throws Exception; vs 如果这对我来说是正确的,那么总是抛出异常而从不指定特定的异常是有意义的。我是不是错过了什么重要的东西?它至少对性能有影响吗?很多人在抛出和捕获异常之间寻找,但没有人问这个非常基本的问题 除了异常之外,我看不到抛出任何异常的

我想知道仅仅抛出
异常
和抛出特定异常(如
NullPointer异常
)之间有什么区别

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

示例:

void test(String testString) throws Exception;
vs

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


除了
异常
之外,我看不到抛出任何异常的好处

抛出特定异常(而不是泛型异常)是最佳实践。这是因为调用方可能希望以不同的方式处理异常,例如,在WebApi中,您可能希望为ArgumentNullException返回错误的请求响应(400),但您可能希望为其他类型的异常返回不同的结果。例如,您可能实际抛出一个自定义NotFoundException,然后控制器将捕获它并返回一个NotFound响应(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块结束,这使您能够以不同的方式处理这些错误。

您希望引发特定类型异常的原因至少有两个:

  • 如果一个程序因异常而失败,您将有更多的信息来确定出错的原因。将查看
    异常
    FileNotFoundException
    进行比较。后者显然为您提供了更多信息
  • 在某些情况下,代码将希望捕获某些类型的异常。例如,在使用串行端口时,您可能希望捕获和处理
    TimeoutException
    NullReferenceException
    不同

  • 首先,
    异常
    是每个
    异常
    的基本类型。就像
    对象
    代表一切一样

    通过抛出一个特定的
    异常
    ,您可以向消费者提供更多关于发生了什么的信息。 想象一下这样一个场景,在没有消息的情况下,您得到一个普通的
    异常
    ,消费者丢失了。例如,当框架抛出一个
    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.
    }
    

    您可以针对特定的情况抛出特定的异常。您希望抛出特定的异常以表明发生了特定的事情,而不仅仅是说“嘿,有些事情不起作用,应用程序死了,但我不知道为什么!”:)如果您的代码可以以几种不同的方式失败,其中一些可以由调用代码处理,而另一些则无法处理,该怎么办?如果您只抛出
    异常
    ,调用代码应该如何区分它们?可能重复“否则,您的代码甚至无法编译!”-是Java吗?是的。如果抛出一个
    IOException
    ,但既不捕获也不使用
    throws
    声明它,就会出现一个编译错误,文本为“Unhandled exception type IOException”。听起来不错。谢谢+谢谢,我选择@Carl's是因为他加了一个很好的例子。虽然信息很好,但我还是把你的标记出来了。如果你认为这篇文章可以帮助其他初学者抛出异常,请标记这篇文章。如果你也认为我可以使这篇文章更好,请告诉我。谢谢,我选择@Carl's是因为他添加了一个很好的例子。虽然信息很好,但我还是把你的标记出来了。如果你认为这篇文章可以帮助其他初学者抛出异常,请标记这篇文章。如果你也认为我可以使这篇文章更好,请让我知道。很好的例子,我看到了抛出特定异常的重要性。谢谢。如果你认为这篇文章可以帮助其他初学者抛出例外,请投票支持这篇文章。如果你也认为我可以使这篇文章更好,让我知道。
    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.
    }