我有一个关于异常处理的问题。 请考虑遵循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
}
}
有人可以告诉我第二种方法的缺点吗?
答案 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)
答案 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
.....
}