大家好,我是IT修真院郑州分院第6期的学员李亚衡,一枚正直纯洁善良的JAVA程序员
今天给大家分享一下,修真院官网JAVA任务一,深度思考中的知识点——JAVA中的异常处理机制
1.背景介绍
可能每一只程序猿都有这样一个梦想
程序永远不会出现问题,用户输入的数据永远是正确的,逻辑一定没有任何问题 ,选择打开的资源也一定是存在的,连接永远是OK的,内存永远是够用的……
简单来说就是:0 error(s), 0 warning(s)
但是,不存在的...
一场总是不期而至,所以我们要处理异常
异常处理机制:天有不测风云,人有旦夕祸福,Java的程序代码也如此,JAVA远在设计之初就考虑到了这个问题,于是就设计了JAVA的异常处理机制。而发展至今的异常处理机制现在也已经非常的完善。
2.知识剖析
什么是异常处理?
如果某个方法不能按照正常的途径完成任务,
就可以通过另一种路径退出方法。
在这种情况下会抛出一个封装了错误信息的对象。
此时,这个方法会立刻退出同时不返回任何值。
另外,调用这个方法的其他代码也无法继续执行,
异常处理机制会将代码执行交给异常处理器。
异常的分类
java中的异常机制包括Error和Exception两个部分。他们都继承自一个共同的基类Throwable
Error属于JVM运行中发生的一些错误,虽然并不属于开发人员的范畴,但是有些Error还是由代码引起的,比如StackOverflowError经常由递归操作引起
Exception分为两种,检查类型(checked)和未检查类型(unchecked)。检查类型的异常就是说要程序员明确的去声明或者用try..catch语句来处理的异常,而非检查类型的异常则没有这些限制
下面看一张树状图
换一种说法
对于严重的,java通过Error类来描述
对于Error一般不编写针对性的代码对其进行处理
对于非严重的,java通过Exception类来描述
对于Exception可以使用针对性的处理方式进行处理
Java异常处理涉及到五个关键字
分别是:try、catch、finally、throw与throws,每个关键字不能被单独使用
1.try:它里面放置可能引发异常的代码
2.catch:后面对应异常类型和一个代码块,用于表明该catch块用于处理这种类型的代码块,可以有多个catch块。
3.finally:主要用于回收在try块里打开的物力资源(如数据库连接、网络连接和磁盘文件),异常机制总是保证finally块总是被执行。
4.throw:用于抛出一个实际的异常,可以单独作为语句使用,抛出一个具体的异常对象。
5.throws:用在方法签名中,用于声明该方法可能抛出的异常。
3.常见问题
注意点1:只有try块是必须的,也就是说如果没有try块,则不可能有后面的catch块和finally块;
注意点2:catch块和finally块都是可选的,但catch块和finally块至少出现其中之一,也可以同时出现;
注意点3:可以有多个catch块,捕获父类异常的catch块必须位于捕获子类异常的后面;
注意点4:不能只有try块,既没有catch块,也没有finally块;
注意点5:多个catch块必须位于try块之后,finally块必须位于所有catch块之后。
一般情况下,不要再finally块中使用renturn或throw等导致方法终止的语句,因为一旦使用,将会导致try块、catch块中的return、throw语句失效。
4.解决方案
在try块中使用退出虚拟机的语句,不过这会导致整个程序终止,最好还是不要在finally中写return和throw语句
5.编码实战
public classTest1 {
public static voidmain(String[] args) {
inta =6;
intb =0;
try{// try监控区域
if(b ==0)throw newArithmeticException();//通过throw语句抛出异常
System.out.println("a/b的值是:"+ a / b);
}
catch(ArithmeticException e) {// catch捕捉异常
System.out.println("程序出现异常,变量b不能为0。");
}
System.out.println("程序正常结束。");
}
}
这个代码主要是使用了Throw语句
public classTest1 {
public static voidmain(String[] args) {
int[] intArray =new int[3];
try{
for(inti =0;i <= intArray.length;i++) {
intArray[i] = i;
System.out.println("intArray["+ i +"] = "+ intArray[i]);
System.out.println("intArray["+ i +"]模"+ (i -2) +"的值: "
+ intArray[i] % (i -2));
}
}catch(ArrayIndexOutOfBoundsException e) {
System.out.println("intArray数组下标越界异常。");
}catch(ArithmeticException e) {
System.out.println("除数为0异常。");
}
System.out.println("程序正常结束。");
}
}
两个catch语句块,主要是为了体会当异常匹配到一个catch后,讲跳出方法,处理异常,其他的catch块不会再有匹配的机会
public classTest2 {
public static voidmain(String args[]) {
inti =0;
String greetings[] = {" Hello world !"," Hello World !! ",
" HELLO WORLD !!!"};
while(i <4) {
try{
//特别注意循环控制变量i的设计,避免造成无限循环
System.out.println(greetings[i++]);
}catch(ArrayIndexOutOfBoundsException e) {
System.out.println("数组下标越界异常");
}finally{
System.out.println("--------------------------");
}
}
}
}
体会finall总会被执行
test1. 需要注意的是,一旦某个catch捕获到匹配的异常类型,将进入异常处理代码。一经处理结束,就意味着整个try-catch语句结束。其他的catch子句不再有匹配和捕获异常类型的机会。
test2.
1)当try没有捕获到异常时:try语句块中的语句逐一被执行,程序将跳过catch语句块,执行finally语句块和其后的语句;
2)当try捕获到异常,catch语句块里没有处理此异常的情况:当try语句块里的某条语句出现异常时,而没有处理此异常的catch语句块时,此异常将会抛
给JVM处理,finally语句块里的语句还是会被执行,但finally语句块后的语句不会被执行;
3)当try捕获到异常,catch语句块里有处理此异常的情况:在try语句块中是按照顺序来执行的,当执行到某一条语句出现异常时,程序将跳到catch语句块,并与catch语句块逐一匹配,找到与之对应的处理程序,其他的catch语句块将不会被执行,而try语句块中,出现异常之后的语句也不会被执行,catch语句块执行完后,执行finally语句块里的语句,最后执行finally语句块后的语句
6.扩展思考
错误处理代码和业务实现代码混杂严重影响程序的可读性,会增加程序维护的难度。在代码健壮性和代码可读性上如何抉择?
针对应用场景选择是否需要使代码更加健壮,程序更加稳定,如果需要,就使用异常处理机制,否则就放弃使用
7.参考文献
http://www.cnblogs.com/maosonglin/p/6096442.html
http://blog.csdn.net/hguisu/article/details/6155636/
http://www.cnblogs.com/Bob-FD/archive/2012/09/23/2699174.html
8.更多讨论
无法穷举所有异常情况,因为人类的知识是有限的,异常情况总比可以考虑到的情况多,总有漏网之鱼,怎么办?
可以自己写出一个异常类进行封装使用,详情请百度搜索:www.baidu.com 关键字:异常类编写
PPT:https://ptteng.github.io/PPT/PPT-java/java-%E5%BC%82%E5%B8%B8%E5%A4%84%E7%90%86%E6%9C%BA%E5%88%B6.html#/
感谢大家观看!
今天的分享就到这里啦,欢迎大家点赞、转发、留言、拍砖~