Java异常处理
2016-02-03 12:47
519 查看
Java异常对性能损耗很大,所以我们要少用异常?
不知道从哪里听来的,关于java很多人都会说java效率低,或者java异常处理非常不好等等一系列的问题.本章主要讨论java的异常,以及异常处理方式.所以我们先来讨论下java处理异常时,时间都花在了哪里.
下面用4个代码片段,并通过比较执行时间来分析java中的异常.
以上时间单位是纳秒.(1秒等于10的9次方纳秒)
A与B的执行时间很相近,A用时0.36秒 B用时0.359秒.从中我们得知,捕获异常对于性能而言是几乎没有性能损耗的.
B用时是0.359秒,C用时是1.43秒,从中可以看出抛出异常将会有很大的性能损失.
本例中平均每次抛出异常将耗时(1437373638-359250837)/1000000=1078.122纳秒
C用时1.43秒,D用时0.44秒(与A和B同一个数量级).同样的抛出异常为什么区别这么大?下面看一看MyException你就会明白了.
从上我们得知:
* try…catch… 对于性能而言几乎是不损耗的.
* 所谓的异常效率低是因为抛出异常导致的.因为在抛出异常时会调用fillInStackTrace方法填充堆栈信息,所以就多花了点时间,但是这是正常的.
* 尽管抛出异常会花费一定的时间,但是真正的业务逻辑中你会像本例中抛出一百万个异常吗?如果感兴趣你可以算算平均每抛出一个异常耗费多长时间.
* 从上我们明白了异常处理大部分时间都耗在哪里了,那么抛出的异常我们如何处理呢?
如何处理异常
我经常听到下面这样的话.* 捕获到异常之后要打印异常信息.
* 自己能处理的就自己处理,自己不能处理的抛到上层让调用方法处理.
PS: 虽然不知道上面什么意思,打算大家都这么说.下面我就说说我对于异常处理.
1.catch块中一定要做点什么.
try { // 处理业务逻辑 } catch (Exception e) { }
只有在你非常确定的情况下才能这么写,否则请不要掩盖问题.
这么写意味着异常不会显示在控制台上,你将发现不了任何问题.
请考虑运维同胞的感受,否则他们会懵B的.我想也许出了问题但是看不到问题在哪里,他们会想杀了这个写代码的家伙.
2.请维护异常链的完整性.
try { int i = 1/0; } catch (Exception e) { e.printStackTrace(); throw new RuntimeException("处理业务A异常, 异常原因 : " + e.getMessage() ); }
也许我们经常会看到上面那样的书写方式.先打印异常,然后抛出异常并添加一点自己的信息描述.
看出来好像也没啥问题啊?不挺正常的吗?我们来看看控制台的异常信息.
异常信息一共4行,前两行是打印的,后两行是抛出的之后虚拟机捕获到然后打印的.
从中我们知道了,异常不停往上抛,如果虚拟机捕获到了,那么将会将异常打印出来.
我们在看看下面一段代码
对比两张控制台的异常信息你会发现,下面的异常很容易理解.处理业务有问题,问题原因Caused by:XXX
而上面的处理方式把异常链断开了.导致异常断断续续的,并不是很容易理解.同时还重复打印了相同异常描述/ by zero
下面的方式维护了异常链的完整性,所以你可以很清楚的看明白问题出在哪里,由谁引起的.
但是你会发现,下面的异常信息有6行,但是第一和第二行和第五和第六行一样的.所以我们可以这么做
从中我们可以发现 抛出异常时,请把捕获的异常当作参数传递下去从而维护异常链完整性.
如果你在catch中抛出异常了,那么就别打印了.不然异常信息会重复.
3.如何抛出异常
异常产生的原因很多,但是90%以上的原因都是因为输入参数不合法导致的.如果是jdk抛出的异常(例如空指针或者解析问题)这种只需要我们捕获并处理就行了.
有时候我们需要自己抛出异常.例如
但是这个显示是RuntimeException,并不是和符合情景.我们是参数无效.所以应该抛出IllegalArgumentException异常.
Spring有个工具类,org.springframework.util.Assert.断言工具类
该工具类表示,程序运行到该行,需要具有某种状态.例如某个参数应该是这样,或者什么什么预期是这样的.
如果不是这样,那么将抛出异常.
例如上面表示,运行到这行,这个参数是非空的.但是却发现他没有值,与预期的相差很大,所以就异常了.
从中我们可以发现,抛出异常时,异常最好能够表示属于什么异常.例如空指针是NullPointerException.
另外,善用工具类对提高代码的水平也很有帮助,同时也增加了代码健壮性.避免动不动就抛出异常.
异常的分类
异常有两种,一种是运行时异常(非检查) 一种是检查异常.非检测异常
书写时,可能抛出异常,但是不提示你.例如Long.valueOf().该方法声明抛出异常.但是你不用显示try…catch…
例如RuntimeException
检查异常
强制你抛出或者try…catch…的异常.例如Exception
相关文章推荐
- Java api 入门教程 之 JAVA的SYSTEM类
- struts2自己定义类型转换器
- Thking in Java---从哲学家就餐问题看死锁现象
- 使用Eclipse将Android项目打Library包
- atitit。自己定义uml MOF EMF体系eclipse emf 教程o7t
- java通过jsp的Excel导出
- java正则表达式的匹配结果遍历方法find()和matches()不同
- java如果读取xml内容
- 举例说明Java设计模式编程中ISP接口隔离原则的使用
- JAVA知识学习
- Java建造者设计模式详解
- 简单理解遵循接口隔离原则的Java设计模式编程
- java 类加载器
- Java代码注释规范详解
- Java 冒泡排序的实现
- Java命令设计模式详解
- JAVA常用基础知识点[继承,抽象,接口,静态,枚举,反射,泛型,多线程...]
- 【持久化框架】SpringMVC+Spring4+Mybatis3集成,开发简单Web项目以及SSM框架下载
- Struts2中的action类
- Java通过UCenter实现Discuz同步登录