码出高效 —异常篇
无论采用什么方式处理异常, 都严禁捕获异常后什么都不做或打印行日志了事。如果在方法内部处理异常, 需要根据不同的业务场景进行定制处理,如重试、回滚等操作。如果向上抛出异常,如上例所示, 需要在异常对象中添加上下文参数、局部变量、运行环境等信息,这样有利于排查问题。
一, 异常分类
所有的异常都是Throwable的子类, 分为Error(致命异常), Exception(非致命异常)
1, error的出现标识着系统发生了不可控的错误
例如`StackOverflowErrorOutfemoryError` 。 针对此类型错误, 程序无法处理, 只能人工介入。
2, Exception 分为 check异常(受检异常)和 uncheck异常(非受检异常)。
2.1, checked 异常是需要在代码中显式处理的异常(必须使用try…catch进行处理), 否则会编译出错。如果能自行处理则可以在当前方法中捕获异常,如果无法处理,贝lj 继续向调用方抛出异常对象。常见的checked 异常包括JDK 中定义的SQLException
,ClassNotFoundException
等。
2.2 在Exception 中, unchecked 异常是运行时异常,它们都继承自RuntimeException
,不需要程序进行显式的捕捉和处理。
三, 最后分析try 代码块与锁的关系
lock 方法可能会抛出unchecked 异常,如果放在try 代码块中,必然触发finally 中的unlock 方法执行。对未加锁的对象解锁会抛出unchecked 异常,如IllegalMonitorStateException
, 虽然是因为加锁失败而造成程序中断的,但是真正加锁失败的原因可能会被后者覆盖。所以在町代码块之前调用lock() 方法,避免由于加锁失败导致finally 调用unlock() 抛出异常。
警示代码中的红色代码应该移到t可代码块的上方,如下所示。
Lock lock = new XxxLock();
try{
lock.lock(); //应该把加锁移动到try前, 避免因为加锁报错, 而去调用unlock。
doSomething();
}finally{
lock.unlock();
}