Java异常处理 - 样式

时间:2009-12-15 19:11:32

标签: java exception-handling

从历史上看,我总是编写我的异常处理代码:

    Cursor cursor = null;
    try {
        cursor = db.openCursor(null, null);
        // do stuff
    } finally {
        if (cursor != null) cursor.close();
    }

但是最近,出于可读性和懒惰的原因,我已经开始这样做了:

        Cursor cursor = db.openCursor(null, null);
        try {           
            // do stuff
        } finally {
            cursor.close();
        }

从try-catch-finally块中分配游标(jdbc句柄,无论如何)是错误的吗?

除非JVM真正炸毁了作业,或者在作业块中的任务和第一行之间,我不确定我的旧样式是否提供任何额外的值,第二行肯定更具可读性简洁。文献generally总是采用第一种风格。

编辑 - 假设我很高兴openCursor抛出的任何异常,同时初始化光标不会被这个代码块捕获,我唯一关心的是这个例子是关闭光标,如果它< strong> 已分配&amp;打开。另外假设我正在测试空值等等.. yadda ... yadda ...(我已经改变了示例以反映这一点,这不是我问题的焦点所以我没有将它包含在第一个版本中)

8 个答案:

答案 0 :(得分:13)

我总是采用第二种方法,因为它允许我将光标设置为final。如果您实际上没有尝试从中捕获异常,我没有理由看到在try子句中有赋值。

编辑:请注意,从进一步的讨论开始。这就是我如何处理抛出异常的openCursor调用:

try
{
    // ALLOCATE RESOURCE
    final Cursor cursor = db.openCursor(null, null);

    try
    {
        // USE RESOURCE
    }
    finally
    {
        // DISPOSE RESOURCE
        cursor.close();
    }
}
catch(OpenCursorException e)
{
    // Handle this appropriately.
}

请注意分配,使用和处置的清晰分离。唯一有趣的是,如果使用try块抛出了您正在捕获分配try块的相同异常。 (IOException将是一个特别好的例子,因为打开和读取都可以抛出一个。)在这种情况下,一切都将仍然清理和正确处置,但你可能错误地将失败归因于初始化异常而不是使用例外。在这种情况下,您需要捕获内部try块中的异常并立即处理它们。

答案 1 :(得分:11)

(更新:问题已根据此答案进行了更正,因此此答案的第一部分不再有意义。)

第一个例子是错误的。如果db.openCursor失败,它将抛出NullPointerException。第二个更好。

顺便说一句,我经常看到第一种方法是这样做的:

Cursor cursor = null;
try {
    cursor = db.openCursor(null, null);
    // do stuff
} finally {
    if (cursor != null) {
        cursor.close();
    }
}

这样做是不安全的,但是这样做是第二种方式,但它经常用在示例中,我看到它在实际代码中使用了很多。

第二种方法更好的一个原因是// do stuff部分中的代码中的错误可以将Cursor设置为null,从而导致游标不会关闭并产生泄漏。总而言之,我认为没有充分的理由使用第一种方法(即使使用空检查进行纠正),以及避免使用它的原因。坚持第二种方法。

(感谢PSpeed的有用评论!)

答案 2 :(得分:6)

不,你终于做对了。

不要分配虚拟值(在这种情况下为null)以禁止编译器有关使用未初始化变量的警告。相反,请注意警告,并正确初始化变量 - 正如您的第二个“懒惰”示例所示。

答案 3 :(得分:6)

如果你在finally中所做的只是关闭光标,那么第二种形式是正确的。如果openCursor()失败,您将从不关闭游标。甚至都没有设置该变量的值。

正如其他人所提到的那样,需要注意的是,如果你正在进行额外的初始化,需要自己进行清理,那么逻辑上必须进入finally {}并相应地更改范围。虽然我认为在这种情况下会进行重组。

底线:正如所写,第一个版本不必要地复杂化。第二个版本是正确的。

编辑:将我的其他评论纳入后人......

第一个例子似乎无害,因为它所做的就是添加一堆不必要的代码。 (完全没必要,如果不清楚的话。)然而,在经典的“更多代码意味着更多潜在的错误”时尚中,有一个隐藏的问题。

如果出于某种原因,“// do something”代码无意中清除了游标变量,那么在你至少得到NullPointerException之前,你将默默地泄漏游标。由于额外的代码绝对没有用,所以额外的风险是完全没必要的。

因此,我愿意将第一个例子称为“完全错误”。我肯定会在代码审查中将其标记出来。

答案 4 :(得分:1)

这样做真的没有错:

Cursor cursor = db.openCursor(null, null);  
  try {  
     // do stuff  
   } finally {  
      try {  
        cursor.close();  
     } catch( SomeOther so ){}  
 }  

答案 5 :(得分:0)

如果openCursor()方法没有抛出异常,后者就没问题了。如果确实如此,那么你肯定想要使用前者。原因是任何异常都会被抛给调用者。如果没有设置调用方法来处理它,则存在问题。

答案 6 :(得分:0)

第二种风格很好只要方法参数都不是一个可以抛出自己的异常并需要清理的计算表达式。

答案 7 :(得分:0)

不同的人有不同的意见。但建议使用第一个选项,因为如果打开光标有任何问题,可以抛出并处理异常。这是一种安全的编程方式。