关于异常处理的几点建议:
一、原则
捕获异常必须处理异常,要么转换成对应文案返回给调用方,要么显式抛出异常给调用方,提醒调用方捕获处理,显式抛出异常时,源异常信息和异常Trace栈信息必须打印出来或者抛给调用方。
二、不符合规范的编码风格
// 不符规范 - 示例一
try {
/* ... */
} catch (Exception e) {
log.info("context"); //-导致结果:异常信息丢失
}
// 不符规范 - 示例二
try {
/* ... */
} catch (Exception e) {
log.info(e.getMessage()); //-导致结果:异常Trace栈信息丢失,无法定位详细出错位置。
}
// 不符规范 - 示例三
try {
/* ... */
} catch (Exception e) {
throw new RuntimeException("context"); //-导致结果:异常信息和异常Trace栈信息丢失
}
三、符合规范的编码风格
//正确处理-示例一
try {
/* ... */
} catch (Exception e) {
log.info(e);//业务可降级,允许失败用info,业务不允许失败,必须用log.error()以便统计报警
}
//正确处理-示例二
try {
/* ... */
} catch (Exception e) {
throw new RuntimeException(e); //携带源异常信息抛给上层业务处理。
throw new RuntimeException("业务异常自定义错误信息",e); //携带源异常信息抛给上层业务处理,并追加定义业务异常错误信息。推荐此方法。
}
//正确处理-示例三
try {
/* ... */
} catch (RuntimeException e) {
log.info(e);
doSomething();//捕捉特定异常,此类异常能预料,且提供了补偿机制
} catch (Exception e) {
//将异常转换为指定异常,此处可以使用业务自定义异常
throw new BussiException(e);//携带源异常信息抛给上层业务处理。
throw new RuntimeException(e);//携带源异常信息抛给上层业务处理。
throw new RuntimeException("业务异常自定义错误信息",e); //携带源异常信息抛给上层业务处理,并追加定义业务异常错误信息。推荐此方法。
}
四、常见可自动降级异常
InterruptedException, NumberFormatException, ParseException and MalformedURLException 等异常,有时候是可以自动降级的。
比如:我们将一个字符串转换为数字,当传入的字符串是非数字类,我们可以给默认值0,但业务必须对0这个值有感知,业务允许0是合法的业务数值,则可以视业务处理成功。如果业务不允许该数值为0,则必须迅速失败并返回错误文案。
int myInteger;
try {
myInteger = Integer.parseInt(myString);
} catch (NumberFormatException e) {
// 出现该异常时,业务可接受指定默认值0
myInteger = 0;
}
最后,再一次提醒: 不要忽略异常不处理!否则你的程序将会莫名其妙出错,却无从查起。