简体   繁体   English

捕获异常 - 为什么有必要?

[英]Catching Exceptions - why is it necessary?

Suppose I have this trivial piece of code, and at runtime list size is 4.假设我有这段微不足道的代码,并且在运行时列表大小为 4。

try{
    for(int i = 0; i < list.size(); i++){
        list.get(10);
    }

}catch(NullPointerException e){
        System.out.println(" exception to string :" + e.toString());
        System.out.println(" exception get class" + e.getClass());
        e.printStackTrace();
}

So the JVM will throw an index out of bounds exception, without having to implement this in the catch block.所以JVM会抛出一个索引越界异常,而不必在catch块中实现这个。

Similarly, if the list is null, the JVM would throw a null pointer exception.同样,如果列表为空,JVM 将抛出空指针异常。

So with that said, why bother to declare an IndexOutOfBoundsException or NullPointerException at all?话虽如此,为什么还要声明 IndexOutOfBoundsException 或 NullPointerException 呢? Why not just declare a generic Exception at the catch block ?为什么不在 catch 块中声明一个通用的 Exception 呢? What is the advantage and disadvantage to this approach?这种方法的优点和缺点是什么?

Usually, you shouldn't catch a generic exception somewhere down in the code because it often indicates a bug in your code which you have to fix.通常,您不应该在代码的某处捕获通用异常,因为它通常表明您的代码中存在您必须修复的错误。

Some checked exceptions (like IOException) which are related to external resources are not within your control, so you should catch them and react to them, but NullPointerExceptions or IndexOutOfBoundException should be avoided by checking the object beforehand.一些与外部资源相关的已检查异常(如 IOException)不在您的控制范围内,因此您应该捕获它们并对其做出反应,但应通过事先检查对象来避免 NullPointerExceptions 或 IndexOutOfBoundException。

As you surely know there are basically two types of exceptions: checked and unchecked.您肯定知道基本上有两种类型的异常:已检查和未检查。 You need to declare or catch checked exceptions but don't have to do that for unchecked ones.您需要声明或捕获已检查的异常,但不必对未检查的异常执行此操作。

So what's the difference?那么有什么区别呢? It often depends on who uses them but generally it's like this:这通常取决于谁使用它们,但通常是这样的:

  • Checked exceptions are thrown for things that are expected to go wrong eventually, eg IOException etc. - a file not being available (not existing, locked etc.) or writable isn't something that never happens and that the developer can try to prevent.对于预期最终会出错的事情,例如IOException等,会抛出已检查的异常——文件不可用(不存在、锁定等)或可写不是永远不会发生的事情,开发人员可以尝试阻止。 Since you have to expect those things to go wrong you'll use a checked exception to either force the method signature to declare those things can go wrong or to catch the exception and handle the case.由于您必须预料到这些事情会出错,因此您将使用已检查的异常来强制方法签名声明这些事情可能会出错,或者捕获异常并处理这种情况。
  • Unchecked exceptions are mostly used for things that can but should not go wrong.未经检查的异常主要用于可能但不应该出错的事情。 In many cases those are due to programming errors (such as NullPointerExceptions, IndexOutOfBoundExceptions etc.) or unexpected system failures (database not available etc.).在许多情况下,这些是由于编程错误(例如 NullPointerExceptions、IndexOutOfBoundExceptions 等)或意外系统故障(数据库不可用等)造成的。 You normally don't catch them explicitly since they're not expected anyways.您通常不会明确捕获它们,因为无论如何它们都不是预期的。

That being said there are situations where checked or unchecked exceptions are used for something else (eg in libraries that need to rely on being able to bubble up a multitude of exceptions and thus wrap checked exceptions un unchecked ones).话虽如此,但在某些情况下,已检查或未检查的异常会用于其他用途(例如,在需要依赖能够冒泡大量异常的库中,从而将已检查的异常包装为未检查的异常)。

As for the catching/declaring in the signature: you'll normally want to be as explicit as possible with checked exceptions, ie you might want to handle an IOException differently than let's say an SQLException .至于签名中的捕获/声明:您通常希望对检查异常尽可能明确,即您可能希望以不同于SQLException处理IOException Unchecked exceptions might be just caught and reported (eg by logging or rethrowing them) but even in those cases you might want to catch some explicitly, eg EJBException s which are thrown by EJBs and which might just be a wrapper for an actual checked exception and thus you might want to unwrap those.未经检查的异常可能只是被捕获和报告(例如,通过记录或重新抛出它们),但即使在这些情况下,您也可能希望明确捕获一些异常,例如 EJB 抛出的EJBException s,它可能只是实际检查异常的包装器和因此你可能想要打开它们。

A final word on NullPointerException : you'll probably never want to catch those explicitly since they shouldn't occur in the first place (either make sure nothing is null or check before accessing those things) and often there are so many things that could be null in a try-block (directly and in the methods that are called) that you'd have a hard time to implement a reasonable reaction.关于NullPointerException的最后一句话:您可能永远不想明确捕获那些,因为它们不应该首先发生(确保没有任何内容为空或在访问这些东西之前检查)并且通常有很多事情可能是在 try 块中(直接在调用的方法中)为 null,您将很难实现合理的反应。 In those cases it's best to just catch any unhandled exception (as is done for threads anyways) and report them to the developer so they can have a look and fix the problem.在这些情况下,最好只捕获任何未处理的异常(无论如何对线程所做的)并将它们报告给开发人员,以便他们可以查看并解决问题。

In order to understand why you may want to use more specific exceptions in your catch block instead of just the generic Throwable (which means EVERYTHING that can possibly go wrong), you may want to consider what it is that is going on here.为了理解为什么您可能想要在 catch 块中使用更具体的异常,而不仅仅是通用的Throwable (这意味着可能出错的一切),您可能需要考虑这里发生了什么。

When creating software that is to be run in production for years, you need it to be very, very robust.在创建要在生产中运行多年的软件时,您需要它非常非常健壮。 This mean that you want your code to be able to handle any situation gracefully, and keep running even though something went wrong.这意味着您希望您的代码能够优雅地处理任何情况,并且即使出现问题也能继续运行

In the particular code you are showing it might very well be that it is perfectly acceptable that the list is too short (a library that occasionally misbehaves) but it is a fatal and unforeseen error if list is null.在您展示的特定代码中,很可能列表太短(一个偶尔行为不端的库)是完全可以接受的,但如果list为空,这是一个致命的和不可预见的错误。

The simplest way to differentiate is to use the way that the exception hierarchy is designed, and have different catch-blocks.最简单的区分方法是使用异常层次结构的设计方式,并具有不同的捕获块。

Also, if you use Java 7 or later, you can create a combined catch block using a pipe sign which allows you to retain the original exception even if the handling code is the same.此外,如果您使用 Java 7 或更高版本,您可以使用管道符号创建一个组合的 catch 块,即使处理代码相同,它也允许您保留原始异常。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM