(一)什么是java里的异常
由于java是c\c++ 发展而来的, 首先我们先看看c语言里的错误.
1.c语言里的错误
我们实现一个程序的过程包括, 代码编写, 编译代码成为程序, 执行程序.其中大部分常见的语法错误都会被编译代码这样部过滤掉. 但是即使通过了编译. 执行程序这一步可能还是会有错误.
原因很多, 例如常见的除数为0, 内存溢出(数组的index超出界限), 或者内存被其他程序修改等.
#include <stdio.h> int f(int a, int b){ return a/b; } int main(){ int i = f(8,0); printf("i is %d\n",i); return 0; }
c语言里对这种执行时出现的错误是无能为力的, 一旦出错就会整个程序崩溃, 就不会在继续执行下面的代码.而且很多时候出错信息很少, 让你无法判断出错的原因和地方, 只能一步步小心debug...
所以很多用c写的程序有时会出现非法关闭的现象.解决方法只能是在代码里对可能出错的地方添加if 判断.
2.java里运行时出现的错误
java里编译器对代码的规范性比c严格得多. 但是即使如此, 通过编译的java程序有时也很难避免执行时出错.
package Exception_kng; class Exp1{ public int f(int a, int b){ return a/b; } } public class Expt_1{ public static void g(){ Exp1 e = new Exp1(); int i = e.f(8,0); System.out.printf("i is %d\n", i); } }
jvm虚拟机是会对错误作出一定的处理的.所以可以简单地将java里的异常理解成java运行时出现的错误, 异常机制就是对这种错误进行处理的机制.
3.java异常的定义
异常是指程序在运行过程中发生的,由于外部问题导致的程序运行异常事件,异常的发生往往会中断程序的运行。在 Java 这种面向对象的编程语言中,万物都是对象,异常本身也是一个对象,程序发生异常就会产生一个异常对象。
- 异常 :指的是程序在执行过程中,出现的非正常的情况,最终会导致JVM的非正常停止。
- 异常指的并不是语法错误,语法错了,编译不通过,不会产生字节码文件,根本不能运行。
- 在Java等面向对象的编程语言中,异常本身是一个类,产生异常就是创建异常对象并抛出了一个异常对象。
- Java为异常设计了一套异常处理机制,当程序运行过程中发生一些异常情况时,程序不会返回任何值,而是抛出封装了错误信息的异常对象。这样保证程序代码更加优雅,并提高程序的健壮性。 为什么要设计异常呢?首先,引入异常之后,我们就可以把错误的代码从正常代码中分离出来进行单独处理,这样使代码变得更加整洁;其次,当出现一些特殊情况时,我们还可以抛出一个检查异常,告知调用者让其处理。
可能出现的异常的代码并不是肯定会出现异常, 取决于执行环境和数据.!
(二)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里对异常的处理有三种.
1.使用try catch处理
package Exception_kng; class Exp2{ public int f(int a, int b){ int i = 0; try{ i = a/b; } catch(Exception e){ System.out.printf("Exception occurs!!\n"); System.out.println(e.getMessage()); //print the root cause System.out.printf("===========================\n"); e.printStackTrace(); //print the info of function stuck. } return i; } } public class Expt_2{ public static void g(){ Exp2 ex = new Exp2(); int i = ex.f(8,0); //call f() System.out.printf("i is %d\n", i); //successfully executed } }
在f()函数中对可能出现的异常的代码进行try catch处理后, 程序会执行catch里的代码. 而且不会中断整个程序, 继续执行try catch后面的代码.
也就是说try catch处理后并不会终止程序, 程序即使出现了错误, 也可以对错误进行一定的处理后继续执行. 这就是java异常机制比c语言安全的地方.
- 注:
- getMessage() 方法: Exception类的方法之一, 返回异常的原因, 上面的 / by zero 就是这个方法输出的.
- printStackTrace(): Exception类的方法之一, 在屏幕输出函数栈信息, 也就是异常出现的地方.
2.使用throw or throws 关键字
函数里并不处理异常, 使用throw or throws 关键字 把可能出现的异常抛给调用该函数的上级函数处理.
例如我在f()函数中不想处理可能出现的异常, 想把它抛出上级函数处理:
package Exception_kng; class Exp3{ public int f(int a, int b){ if (0 == b){ throw new ArithmeticException("Shit !!! / by zero!"); } return a/b; } } public class Expt_3{ public static void g() throws ArithmeticException{ Exp3 ex = new Exp3(); int i = 22; i = ex.f(8,0); //throw excetpion System.out.printf("i is %d\n", i); //failed executed System.out.printf("g() is done!!\n"); //failed executed } public static void h(){ try{ g(); }catch(ArithmeticException e){ System.out.printf("Exception occurs!!\n"); System.out.println(e.getMessage()); //print the root cause System.out.printf("===========================\n"); e.printStackTrace(); //print the info of function stuck. } System.out.printf("h() is done!!\n"); //successfully executed } }
可以见到f() 加了个条件判断, 如果参数b = 0, 使用throw 直接手动抛出1个异常. 让调用它的函数处理.
g()调用f()函数, 预见到f()可能有异常, 但是也不想处理, 使用throws 关键字告诉调用它的函数本函数有可能抛出这种异常. // 注, 这里的throws对程序并没有实质的影响.
h()调用g(), 简单g()定义的throws, 用try catch在本函数进行处理.
注意这个程序没有执行g() 最后的代码.
3.交给jvm虚拟机处理
假如上面的例子h() 也不处理怎么办? 就如(一)中 2 的例子, 会抛给jvm处理.
package Exception_kng; class Exp1{ public int f(int a, int b){ return a/b; } } public class Expt_1{ public static void g(){ Exp1 e = new Exp1(); int i = e.f(8,0); System.out.printf("i is %d\n", i); } }
但是这种情况只适用于RuntimeExecption及其派生类.
jvm怎么处理呢, 就是中断整个程序, 并把异常信息输出到屏幕上.
- 实际上, 当java程序的一个函数抛出异常时,
- 首先会检查当前函数有没有try catch处理, 如果无检查上一级函数有无try..catch处理....
- 这样在函数栈里一级一级向上检查, 如果直至main函数都无try..catch, 则抛给jvm..
项目中强烈建议尽量手动处理, 不要把异常交给jvm.
标签:Java,int,System,处理,java,异常,public From: https://www.cnblogs.com/imreW/p/17366896.html