异常处理问题

时间:2010-02-22 05:21:27

标签: java exception-handling

我有一个关于异常处理的问题。 请考虑遵循Java代码段。

        try{
            //code
        }catch(SubSubException subsubex){
            //code
        }catch(SubException subex){
            //code
        }catch(Exception ex){
            //code
        }

我知道这是处理异常的推荐方法。但是我可以通过使用以下代码片段来实现同样的目的。

        try{
            //code
        }catch ( Exception ex){
            if( ex instanceof SubException){              
                //code
            }else if(ex instanceof SubSubException){
                //code
            }else{
                //code
            }
        }

有人可以告诉我第二种方法的缺点吗?

8 个答案:

答案 0 :(得分:111)

第二种方法不太可读。此外,即使你的“聪明”技巧是使用instanceof关键字,口袋妖怪异常处理也永远不会成为可能。无论如何,我不是在开玩笑或嘲笑你,但最好是为人类编写代码来阅读和维护,而不是为计算机编写代码。

答案 1 :(得分:40)

是的,MadMurf指出了最重要的区别:在编译时进行可达性检查。标准习惯用法会抓住这样的东西并正确地防止它编译:

    try {
    } catch (IndexOutOfBoundsException iooe) {
    } catch (ArrayIndexOutOfBoundsException aiooe) {
    }

原始问题中提出的if / instanceof analog会编译(这不是你想要的,因为它是错误的)。

标准习语在编译时捕获错误的原因在JLS 14.21 Unreachable Statements中给出。

  
      
  • 如果满足以下两个条件,则可以访问catch块C:      
        
    • [...]
    •   
    • 在try语句中没有早期的catch块,因此C的参数类型与A参数类型的子类相同。
    •   
  •   

为了进一步说明这一点,以下编译:

    try {
    } catch (Exception e) {
        if (e instanceof Exception) {
        } else if (e instanceof Exception) {
        }
    }

正如你所看到的,这种“口袋妖怪捕捉”成语更难维护,因为它绕过了标准习惯用法中强制执行的一些编译时可达性检查。

为了更清楚地表明这一点,无论你是否故意这样做,你实际上都重新排列了原始问题中检查异常的顺序,这个事实很容易被其他人忽略。如果SubSubException是SubException的子类,则永远不会评估第二个if条件,并且它的主体实际上是无法访问的代码。

if / instanceof方法非常容易出错。

答案 2 :(得分:23)

嗯,为什么你甚至不得不做第二种方法?记住这一点,除非其他选项在性能,可读性等方面更好,否则你应该遵守惯例。 catch语句最初是为了处理异常类型的分类而拥有自己的,所以请按原样使用它们......只是一个想法!...

答案 3 :(得分:4)

第二种情况是完全有效的java代码,但它有更大的Cyclomatic complexity而没有添加任何额外的值。

答案 4 :(得分:4)

第二种方法的可读性明显较低,因为:

  • 它需要更多符号,

  • 需要更深的缩进,

  • 这不是惯用语。

IMO,最后一个是最重要的。您应该以其他 Java程序员期望编写代码的方式编写代码。

答案 5 :(得分:2)

在第二个例子中重新排序你的“捕获”异常。如果SubSubException扩展SubException,则永远不会达到第二次检查....

在订购鱼类时要小心谨慎......

除了在别处提到的问题之外,问题必须是为什么在第一种方式尝试第二种方式时,为标准并且可读?

答案 6 :(得分:1)

考虑第一个块中的代码测试异常的类型,测试一次基本异常(在第二位代码中,您在某种程度上测试基本异常两次)并且缩进较少(因此逻辑较少)对于grok),我的想法是第一个更好,更容易理解等。

缺点: - 更难理解

答案 7 :(得分:1)

我认为,更好(更具可读性):

 try {    
   .....
 } 
 catch (IndexOutOfBoundsException iooe) {    } 
 catch (ArrayIndexOutOfBoundsException aiooe) {    }
 .....

  try {
     .....
  } 
  catch (Exception e) {
     if (e instanceof Exception) {        } else 
     if (e instanceof Exception) {        } else
     .....
  }