首页 » 编写高质量代码:改善Java程序的151个建议 » 编写高质量代码:改善Java程序的151个建议全文在线阅读

《编写高质量代码:改善Java程序的151个建议》建议116:异常只为异常服务

关灯直达底部

异常只为异常服务,这是何解?难道异常还能为其他服务不成?确实能,异常原本是正常逻辑的一个补充,但是有时候会被当作主逻辑使用,看如下代码:


//判断一个枚举是否包含String枚举项

public static<T extends Enum<T>>boolean Contain(Class<T>c, String name){

boolean result=false;

try{

Enum.valueOf(c, name);

result=true;

}catch(RuntimeException e){

//只要是抛出异常,则认为是不包含

}

return result;

}


判断一个枚举是否包含指定的枚举项,这里会根据valueOf方法是否抛出异常来进行判断,如果抛出异常(一般是IllegalArgumentException异常),则认为是不包含,若不抛出异常则可以认为包含该枚举项,看上去这段代码很正常,但是其中却有三个错误:

异常判断降低了系统性能。

降低了代码的可读性,只有详细了解valueOf方法的人才能读懂这样的代码,因为valueOf抛出的是一个非受检异常。

隐藏了运行期可能产生的错误,catch到异常,但没有做任何处理。

我们这段代码是用一段异常实现了一个正常的业务逻辑,这导致代码产生了坏味道。要解决此问题也很容易,即不在主逻辑中使用异常,代码如下:


//判断一个枚举是否包含String枚举项

public static<T extends Enum<T>>boolean Contain(Class<T>c, String name){

//遍历枚举项

for(T t:c.getEnumConstants()){

//枚举项名称是否相等

if(t.name().equals(name)){

return true;

}

}

return false;

}


异常只能用在非正常的情况下,不能成为正常情况的主逻辑,也就是说,异常只是主场景中的辅助场景,不能喧宾夺主。

而且,异常虽然是描述例外事件的,但能避免则避免之,除非是确实无法避免的异常,例如:


public static void main(Stringargs){

File file=new File("文件.txt");

try{

FileInputStream fis=new FileInputStream(file);

/*其他业务逻辑处理*/

}catch(FileNotFoundException e){

//异常处理

}

}


这样一段代码经常会在我们的项目中出现,但经常写并不代表不可优化,这里的异常类FileNotFoundException完全可以在它诞生前就消除掉:先判断文件是否存在,然后再生成FileInputStream对象,代码如下:


public static void main(Stringargs){

File file=new File("文件.txt");

//经常出现的异常情况,可以先做判断

if(fle.exists()&&!fle.isDirectory()){

try{

}catch(){

}

}

}


虽然增加了if判断语句,增加了代码量,但是却会减少FileNotFoundException异常出现的几率,提高了程序的性能和稳定性。

注意 异常只为确实异常的事件服务。