防止异常与捕获Java中的异常

时间:2009-05-21 20:02:34

标签: java exception error-handling

我想知道其他SOers在实践中如何处理和/或防止例外。

在什么情况下你会阻止例外,以及如何? 在什么情况下你会捕获异常?

我通常会通过if(foo!=null) {...}

来预防'NullPointerExceptions'(和其他类似的')

我发现在大多数情况下,这比使用try-catch块所涉及的所有内容都要小。

当潜在的异常更复杂或更多时,我会使用try-catch块。

13 个答案:

答案 0 :(得分:23)

在我看来,当引用为空(例如,再次)实际表示有效程序状态时,仅防止NullPointerException(例如)是有意义的。如果没有,你应该阻止它发生,因为在这种情况下你想要程序会死硬。

特别是在Java中,从RuntimeException降序的某些异常(例如IllegalArgumentException)实际上是指示编程错误,如果程序正确则不应该发生这种情况。我试着遵循这个。如果我正在编写一个对其参数设置限制的方法,我不会试图避免抛出异常。我会积极地抛出一个。

答案 1 :(得分:11)

如果可以防止异常,那么编程实践就更好了。例如,任何NullPointerException通常都表示编程错误IMO。 (这是一个RuntimeException的原因之一。)

当您期望能够在一层代码中检测到失败条件时,异常更有用,但您不希望在那里处理失败条件,而是在更高级别的代码中处理失败条件。也就是说,您打算在堆栈中抛出多于一帧的异常 - 或者一直向上抛出堆栈。当您不希望程序能够有意义地处理问题时,例外也很有用。

答案 2 :(得分:6)

three kinds例外。

运行时异常始终是可以阻止的。你只需要正确编程。

如果可能的话,

检查异常应转换为正确的抽象级别(如果他不知道/不关心SQL异常,则不向用户抛出SQLException)或在更高级别处理(也就是说,让它们弹出)并显示/记录正确的信息。

错误根本不应该处理。

有关如何防止RuntimeExceptions

的更多详细信息,请参阅该链接

答案 3 :(得分:5)

抓住您知道如何处理它们的例外情况。

你不应该在任何地方检查(foo!= null),检查foo首次使用的位置。之后只需使用foo而无需检查。如果foo在确定它不为null后突然变为null,则会出现大问题。那么例外是恰当的。

try {
   foo();
}
catch (FooException e) {
}

是一种糟糕的代码味道,应该避免

答案 4 :(得分:3)

我将检查方法开头的输入参数,如果它们超出应该传递给方法的范围,则抛出IllegalArgumentException。这个想法是它是一个编程错误,应该修复它。现在比现场更好。如果在方法的中间我得到一个意外的条件(在列表中为null等),我将记录一个致命的消息并执行System.exit(2)。这又强迫你解决一个问题,而不仅仅是记录它并继续前进。

答案 5 :(得分:2)

避免使用那些(NullPointerExceptions,NullReferenceExceptions等)。

抓住那些有点棘手的问题(Sql错误......它们可能在你无法控制的地方,但你需要优雅地清理它们)。

答案 6 :(得分:2)

我希望我的所有例外都能向上移动,除非它们是次要的,然后我会吞下它们(例如:因为电子邮件通知函数产生了NPE而阻止索赔条目死亡...我想吞下那个NPE并保持卡车运输只要程序真正的肉没有例外)。

我使用此方法强制Java的大部分不可恢复但已检查的异常:

http://www.onjava.com/pub/a/onjava/2003/11/19/exceptions.html

答案 7 :(得分:2)

一般来说,例外情况应该是特殊的,例如:不可预见的或由于编程错误。 问题是,Java类库中存在一些可疑的设计描述,因此您最终会得到如下习语:

class Foo {
  static BufferedReader in=new BufferedReader(new InputStreamReader(System.in));
  int getInt() throws IOException {
    int r=0;
    for(;;) {
      String s=in.readLine();
      try {
        r=Integer.parseInt(s);
        break;
      }
      catch(NumberFormatException e) {
        System.out.println("Please enter a valid integer.");
      }
    }
    return r;
  }
}

显然代码并不完美(会在EOF上抛出NullPointerException),但它表明了对实际上并不例外的事情使用异常的问题。

答案 8 :(得分:2)

我在整个代码中使用以下类来验证和中止处理:

@Getter
@Setter
public class Abort<T> {

    private boolean abortProcessing;

    private T response;
}

@Getter @Setter public class Abort<T> { private boolean abortProcessing; private T response; }

这样您就可以立即验证或捕获异常,记录它们并返回中止对象。

答案 9 :(得分:1)

通常,如果这样做是合理的,您应该尝试首先防止发生异常。很多时候,这是不合理的,也可能是不可能的(尤其是当涉及到io时),但这就是try / catch的用途。特别是,这意味着您应该始终检查指针和数组索引,以防止NullPointerException和ArrayIndexOutOfBoundsException。当然,除非你无能为力,否则无论如何都要重新抛出它。

答案 10 :(得分:1)

你应该抓住所有例外。使用简单的NullPointerException语句始终可以阻止if。像大多数IOException一样,其他一些例外很难被阻止。除了需要使用try / catch块的样板文件外,如果你的类抛出异常,那么将创建该异常的对象并且它必须被垃圾收集...所以通过不抛出异常,你也可以使你的VM更健康。

答案 11 :(得分:1)

通常,当异常导致进程中止时,我会使用异常。当我要对问题采取某些措施并以某种方式恢复时,我会尝试防止异常发生。

就像,如果将参数传递给子例程并且我合理地期望它可能为null,我将检查它是否为null。例如,在现实生活中,null String通常等效于零长度String,我将在其中写入&lt; if(s == null)s =“”;取代。

但是如果一个null String意味着某些东西出现了严重错误,我们应该退出整个过程并向用户显示一个“恐慌 - 中止 - 世界即将结束”类型的消息,那么异常非常方便。您可以将异常方式深入到子程序的多个层中,只需在顶部捕获它,显示消息,然后就完成了。

我经常为这些条件创建自己的例外。我的许多程序都附带了像&lt;抛出新的BadInputException(“找不到客户编号”)&gt;让我出去,显示一条消息,然后退出。这实际上节省了IF的深层嵌套和从子程序不断检查返回值。

答案 12 :(得分:1)

我尽可能地防止,但是我抓住用户影响的东西,例如当他们输入错误类型的数据时。在Java中,我有一个我编写的类,它扩展了Scanner并一直要求正确的输入,直到它有效。 (来自CLI)