最近,无意中看到了别人的某段代码,是用抛出异常的方式去控制代码逻辑和流程。
比如,程序设置了几种分流策略,在rpc层的一个调用会判断当前请求该走哪个策略。但是当rpc发生异常时,catch之后返回null,然后在主流程中,对rpc结果进行判断,主动抛出异常,然后在外层catch住,打印异常日志,归到默认策略,返回空的response。
这个倒不是说不可以,但是我个人是不赞成用这种抛出异常的方式去控制逻辑的。我更倾向于在主流程检测到策略信息为空时,直接返回空的result,而不是抛异常让外层catch.
因为相比于普通的new一个类或对象等操作,new一个异常 和catch一个异常是非常耗时的。
就上面的代码来说,都运行1万次,四种行为的耗时大概是:
建立基础对象: 210万ns 建立继承对象: 490万ns 新建异常对象: 2270万ns 抛出并捕获异常: 10170万ns
我们可以看到,基础对象和继承对象的创建在同一个数量级,而创建异常对象的耗时要比前两者高一个数量级,而抛出异常并捕获,又高了一个数量级。所以,catch 异常是很耗时的。
所以,个人认为,在认为程序可能发生异常的关键点加try chtch 就够了,不要用这种机制去做逻辑控制。可能写的省事,但效率上就要打些折扣了。
那么,为什么捕获异常会耗时严重呢。我们知道 ,Java所有的异常都是继承自 Throwable,它的构造函数中有一个native方法:fillInStackTrace(),这个方法,在新创建一个异常对象时,会把堆栈信息都存一遍,即使你不用,它也不会不给你存,这个大概就是耗时的地方了。