Java⾥的异常(Exception)详解
作为⼀位初学者, 本屌也没有能⼒对异常谈得很深⼊.  只不过⾥关于Exception的东西实在是很多. 所以这篇⽂章很长就是了..⼀, 什么是java⾥的异常
由于java是c\c++ 发展⽽来的,  ⾸先我们先看看c语⾔⾥的错误.
1.1 c语⾔⾥的错误
我们实现1个程序的过程包括,  代码编写, 编译代码成为程序,  执⾏程序.
.
其中⼤部分常见的语法错误都会被编译代码这样部过滤掉.  但是即使通过了编译. 执⾏程序这⼀步可能还是会有错误.
原因很多, 例如常见的除数为0,    内存溢出(数组的index超出界限), 或者内存被其他程序修改等.
最简单的例⼦:
[java]
1. #include <stdio.h>
2.
3. int f(int a, int b){
4.    return a/b;
5. }
6.
7. int main(){
8.    int i = f(8,0);
9.        printf("i is %d\n",i);
10.    return 0;
11. }
上⾯的例⼦编译时是⽆错的,  但是⼀旦执⾏就会提⽰吐核错误了.
c语⾔⾥对这种执⾏时出现的错误是⽆能为⼒的,  ⼀旦出错就会整个程序崩溃, 就不会在继续执⾏下⾯的代码.
⽽且很多时候出错信息很少, 让你⽆法判断出错的原因和地⽅, 只能⼀步步⼩⼼
所以很多⽤c写的程序有时会出现⾮法关闭的现象.
解决⽅法只能是在代码⾥对可能出错的地⽅添加if 判断.
例如f()函数⾥可以对b进⾏判断, 如果是0就不执⾏.
1.2 java⾥运⾏时出现的错误
java⾥编译器对代码的规范性⽐c严格得多. 但是即使如此,  通过编译的java程序有时也很难避免执⾏时出错.
例如, 将上⾯的c程序改编成java程序:
[java]
1. package Exception_kng;
2.
3. class Exp1{
4.    public int f(int a, int b){
5.        return a/b;
6.    }
7. }
8.
9. public class Expt_1{
10.    public static void g(){
11.        Exp1 e = new Exp1();
12.        int i = e.f(8,0);
13.        System.out.printf("i is %d\n", i);
14.    }
15. }
运⾏时⼀样会出错, 下⾯是出错信息:
[java]
1. [java] Caused by: java.lang.ArithmeticException: / by zero
2. [java]  at Exception_kng.Exp1.f(Expt_1.java:5)
3. [java]  at Exception_kng.Expt_1.g(Expt_1.java:12)
4. [java]  at Enter_1.main(Enter_1.java:31)
但是可以见到, java告诉你出错的类型: 运算错误(ArithmeticExcetion), 出错信息和出错的类与⽂件⾏数输出, ⽅便你调试.  jvm虚拟机是会对错误作出⼀定的处理的.
所以可以简单地将java⾥的异常理解成java运⾏时出现的错误,  异常机制就是对这种错误进⾏处理的机制.
1.3 java异常的定义
实际上, 当java程序执⾏时出现错误时, jvm会把执⾏时出错的信息(例如出错原因, 类型, 位置) 收集,然后打包成为1个对象(object),  程序员可以对这种对象进⾏处理. 这种对象就是所谓的异常.
可能出现的异常的代码并不是肯定会出现异常, 取决于执⾏环境和数据.!
⼆, java⾥的异常的分类.
见下图:
Throwable
/                \
Error            Exception
/                  /              \
xxxxxx            xxxxxx          RuntimeException
/                  \
xxxxxx            ArithmeticException
上图的所有对象都是类.
Throwable 代表是可抛出的.
Error            代表的是严重错误,  这种错误程序员⽆法进⾏处理, 例如操作系统崩溃, jvm出错, 动态链接库失败等.  Error并不是异常, 不是本⽂的重点.
Exception    代表的就是异常了.  它下⾯很多派⽣类,  其中它的派⽣类也分两种, ⼀种是RuntimeException(运⾏时异常), 其他的都是⾮运⾏时异常
RuntimeException    包括除数为0, 数组下标超界等. 运⾏时异常的派⽣类有很多, 其产⽣频率较⾼.  它的派⽣类可以由程序处理或者抛给(throw) 给jvm处理. 例如上⾯的例⼦就是抛给了jvm处理, jvm把程序中断执⾏, 并把错误信息输出到终端上.
⾮RuntimeExcption  这种异常属于Excepion的派⽣类(上⾯红⾊的xxx), 但是不是RuntimeException的派⽣类,  这种异常必须由程序员⼿动处
理,否则不通过编译.
ArithmeticExcpetion  算术异常, 它是RuntimeException的派⽣类, 所以程序员不⼿动处理也通过编译, 只不过出错时会被jvm处理.
三, java⾥对异常的处理
java⾥对异常的处理有三种.
3.1 程序猿对有可能出现的异常使⽤try catch处理.
例如我们将上⾯的例⼦改动⼀下:
[java]
1. package Exception_kng;
2.
3. class Exp2{
4.    public int f(int a, int b){
5.        int i = 0;
6.        try{
7.            i = a/b;
8.        }
9.        catch(Exception e){
10.            System.out.printf("Exception occurs!!\n");
11.            System.out.Message());  //print the root cause
12.            System.out.printf("===========================\n");
13.            e.printStackTrace(); //print the info of function stuck.
14.        }
15.
16.        return i;
17.    }
18. }
19.
20. public class Expt_2{
21.    public static void g(){
22.        Exp2 ex = new Exp2();
23.        int i = ex.f(8,0); //call f()
24.        System.out.printf("i is %d\n", i);  //successfully executed
25.    }
26. }
在f()函数中对可能出现的异常的代码进⾏try catch处理后,  程序会执⾏catch⾥的代码. ⽽且不会中断整个程序, 继续执⾏try catch后⾯的代码.程序执⾏输出:
[java]
1. [java] Exception occurs!!
2. [java] / by zero
3. [java] ===========================
4. [java] java.lang.ArithmeticException: / by zero
5. [java]  at Exception_kng.Exp2.f(Expt_2.java:7)
6. [java]  at Exception_kng.Expt_2.g(Expt_2.java:23)
7. [java]  at Enter_1.main(Enter_1.java:31)
8. [java] i is 0
注意最终也执⾏了g()函数中的最后⼀条语句, 输出了i的值.
也就是说try catch处理后并不会终⽌程序, 令程序即使出现了错误,  也可以对错误进⾏⼀定的处理后继续执⾏. 这就是java异常机制⽐c语⾔安全的地⽅.
下⾯会详细讲解 try catch.
注:
getMessage() ⽅法:  Exception类的⽅法之⼀,  返回异常的原因,  上⾯的 / by zero 就是这个⽅法输出的.
printStackTrace():      Exception类的⽅法之⼀,  在屏幕输出函数栈信息,  也就是异常出现的地⽅.
3.2 函数⾥并不处理异常, 使⽤throw or throws 关键字把可能出现的异常抛给调⽤该函数的上级函数处理.例如我在f()函数中不想处理可能出现的异常,  想把它抛出上级函数处理:
下⾯是个例⼦:
[java]
1. package Exception_kng;
2.
3. class Exp3{
4.    public int f(int a, int b){
5.        if (0 == b){
6.            throw new ArithmeticException("Shit !!! / by zero!");
7.
8.        }
9.
10.        return a/b;
11.    }
12. }
13.
14. public class Expt_3{
15.    public static void g() throws ArithmeticException{
16.        Exp3 ex = new Exp3();
17.        int i = 22;
18.        i = ex.f(8,0); //throw excetpion
19.        System.out.printf("i is %d\n", i);  //failed executed
20.        System.out.printf("g() is done!!\n");  //failed executed
21.    }
22.
23.    public static void h(){
24.        try{
25.            g();
26.        }catch(ArithmeticException e){
27.            System.out.printf("Exception occurs!!\n");
28.            System.out.Message());  //print the root cause
29.            System.out.printf("===========================\n");
30.            e.printStackTrace(); //print the info of function stuck.
31.        }
32.
33.        System.out.printf("h() is done!!\n");  //successfully executed
34.    }
35. }
可以见到f() 加了个条件判断, 如果参数b = 0, 使⽤throw 直接⼿动抛出1个异常. 让调⽤它的函数处理.
g()调⽤f()函数, 预见到f()可能有异常, 但是也不想处理,  使⽤throws 关键字告诉调⽤它的函数本函数有可能抛出这种异常. // 注, 这⾥的throws 对程序并没有实质的影响.
h()调⽤g(),  简单g()定义的throws, ⽤try catch在本函数进⾏处理.
输出:
[java]
1. [java] Exception occurs!!
2. [java] Shit !!! / by zero!
3. [java] ===========================
4. [java] java.lang.ArithmeticException: Shit !!! / by zero!
5. [java]  at Exception_kng.Exp3.f(Expt_3.java:6)
6. [java]  at Exception_kng.Expt_3.g(Expt_3.java:18)
7. [java]  at Exception_kng.Expt_3.h(Expt_3.java:25)
8. [java]  at Enter_1.main(Enter_1.java:31)
9. [java] h() is done!!
注意这个程序没有执⾏g() 最后的代码.
throw 和 throws 后⾯也会详细讲解.
3.3 交给jvm虚拟机处理
假如上⾯的例⼦h() 也不处理怎么办?  就如1.2 的例⼦, 会抛给jvm处理.
但是这种情况只适⽤于RuntimeExecption及其派⽣类.
jvm怎么处理呢,  就是中断整个程序, 并把异常信息输出到屏幕上.
实际上, 当java程序的1个函数抛出异常时,
⾸先会检查当前函数有没有try catch处理, 如果⽆检查上⼀级函数有⽆atch处理....这样在函数栈⾥⼀级⼀级向上检查, 如果直⾄main函数都⽆atch, 则抛给jvm..
项⽬中强烈建议尽量⼿动处理, 不要把异常交给jvm.
四,Try catch finally 的处理机制.
这⾥开始详解try catch finally了.
语法是这样的.
try{
可能出异常的若⼲⾏代码;
}
catch(ExceptionName1 e){
产⽣ExceptionName 1的处理代码;
}
catch(ExceptionName2 e){
产⽣ExceptionName 2的处理代码;
}
...
finally{
⽆论如何, 最终肯定会执⾏的代码
}
java中index是什么意思4.1 try catch finally的执⾏路线.
下⾯⽤个例⼦来说明:
[java]

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。