前言:
在程序设计和运行的过程中,发生错误是不可避免的。为此java提供了异常的处理机制,来帮助程序员检查可能出现的错误。保证程序的可读性和可维护性。java将异常封装到一个类中,出现错误时就会抛出异常,程序终止。
通过学习,您可以了解到:
1、什么是异常
2、如何捕捉异常
3、java中有哪些常见的异常
4、如何自定义异常
5、如何在方法中抛出异常
6、运行时有哪些异常
7、异常处理的使用原则
一、什么是异常
错误产生于没有实现预料到的各种情况,或是超过了程序员可控制范围的环境因素。
就比如我们经常遇到的遇到除数为0的情况,但是自身又没发现,于是程序运行到这一样是就会让程序异常终止:
① 算术异常
程序运行时发生了算数异常ArithmeticException,根据异常提示可以知道是在Test2的main方法中发生了算术异常,异常为 / by zero,意为0被作为了除数而报错。
可以看到,异常前的程序都会正常执行,当执行到异常,系统就不会再执行下去,提前结束并提示:程序异常退出
Process finished with exti code 1
异常类为ArithmeticException
还有很多例子,例如
②数组越界:
代码案例:
public class Main { public static void main(String[] args) { int[] arr = new int[]{0,1,2,3,4,5}; System.out.println(arr[6]); } }
运行结果:
异常类为ArrayIndexOutOfBoundsException
③空引用的使用(空指针):
代码案例:
public class Main { public static void main(String[] args) { String tem = null; int stringLength = tem.length(); System.out.println(stringLength); } }
执行结果:
异常类为NullPointerException
java是面向对象的计算机语言,所以在java中异常都是作为类的实例的形式出现的。当某一方法中发生错误时,这个方法会创建一个对象,并且把它传递给正在运行的系统。 这个对象就是异常对象,通过异常处理机制,可以将非正常情况下的处理代码与程序的主逻辑分离,即在编写代码主流程时在其他地方处理异常。
这些异常种类和异常处理机制将会在下面的篇章中逐渐渗透。
二、异常处理
为了保证程序能正常的运行,我们需要对出现的异常错误进行及时的处理。在java 的异常处理机制当中,当某个方法出现异常时,可以在该方法里进行捕捉,然后处理异常,也可以将异常向上抛出,交给该方法的调用者处理。
如果对产生的异常不做任何的处理,程序就会异常终止。所以需要对该异常进行捕捉然后处理。
1、如何捕捉异常?
java语言的异常捕捉结构为:
try{
// 可能产生异常错误的语句
}catch( ExceptionTypeOne e){
// 对异常 ExceptionTypeOne 的处理语句
}catch ( ExceptionTypeTwo e) {
// 对ExceptionTypeTwo 的处理语句
}
...........
finally {
// 语句块
}
此结构由 try,catch, finally 3部分组成。其中:
① try语句中的是可能发生异常的代码
② catch用来捕捉异常,{}中为异常处理的语句
③ finally为异常处理的最后执行部分,无论前面的catch是否被捕捉,finally语句都会被执行
其中的 Exception 是try代码块传递给catch代码块的变量类型,e是变量名。
我们使用这种try - catch语句来对上面的 / by zero异常来进行一个修改:
public class Test2 { public static void main(String[] args) { try { int digit = 1; int zero = 0; System.out.println("value of digit is:"+digit); System.out.println("value of zero is:"+zero); int result = digit / zero; System.out.println("value of result is:" + result); }catch (Exception e){ e.printStackTrace(); } System.out.println("hello world!"); } }
catch代码块中的语句e.printStackTrace() 语句时用于输出错误性质,通常,异常处理用下面三个函数来获取异常有关信息:
getMessage() // 输出错误性质
toString() // 给出一场的性质和类型
printStackTrace() // 指出异常类型、性质、栈层次及出现在程序的位置
运行结果如图:
可以发现,digit 和 zero 的值都被打印,但是result的值没有被打印,try - catch 语句外的打印
hello world 的语句也被打印。紧接着的一行就是 Process finished with exit code 0
表示程序正常退出。
当有多个catch 语句的情况:
public class Main { private static int Test(int x, int y) throws MyException{ if(y < 0){ throw new MyException("除数不能为负数"); } return x/y; } public static void main(String[] args) { try { int ret = Test(2,-1); } catch (MyException e) { System.out.println(e.getMessage()); // 进行捕捉 } catch (ArithmeticException e){ System.out.println(e.getMessage()); } catch (Exception e){ System.out.println("发生了其他异常"); } } }
上面实例使用了很多个catch语句来捕捉异常, 其中
① 调用Test (2 , -1 ) 将会发生MyException异常,进而转入catch (MyException e)执行
② 调用Test (3 , 0) 将会发生ArithmeticException异常,转入对应的catch语句执行
③ 如果还有除了 0 和 负数之外的异常,那么将会被Exception e捕捉然后转入catch语句执行
但是由于 Exception是所有异常类的父类,如果将其与MyException调换位置如果图:
那么 前面的 ArithmeticException异常和 MyException 异常都会被 第一个catch语句捕捉,
那么后面的catch语句就不会执行,最后就只会收到一个发生了其他异常的字符串提示,对于异常的处理没有任何的帮助,try - catch语句也就是去了它的意义。
通过try - catch 语句,程序没有异常退出,而是将错误抛出后,继续执行try - catch 异常捕捉后面的语句,而不至于因为一个异常从而影响整个程序的运行。
2、finally语句
一个完整的try - catch 语句一定要包含finally语句,无论程序是否有异常发生,并且无论之间的try - catch语句是否顺利执行完毕,都会执行finally语句。
但是也存在意外,finally语句不会被执行的情况,如下:
① 在finally 语句中发生了异常
② 在前面的代码中使用了System.exit()语句,程序提前结束
③ 程序所有的线程死亡
④ 关闭CPU
3、finally语句中的throw和return
无论有没有异常都会执行finally语句,那么如果在try-catch语句块中遇到了return和throw语句,后面的finally语句是否还会执行呢?代码案例如下:
public class Test { public static void main(String[] args) { System.out.println("return value of getValue(): " + getValue()); } public static int getValue() { try { return 0; } finally { return 1; } } }
程序的运行结果是什么?
解析:当Java程序执行ty块、catch块时遇到了retun语句, 并不会立马结束这个方法,而是去寻找该异常处理流程中是否包含finally语句块,如果没有finally块,方法终止,返回相应的返回值。如果有finally块, 系统立即开始执行finally块中的语句,只有当finally块执行完成后,系统才会再次回到try-catch语句中来根据return语句结束方法。如果finally块里使用了return语句,则finally块会直接执行return语句并返回,使方法结束,系统将不会跳回去执行try块、 catch块里的任何代码。
结果如下:
return value of getValue(): 1
java异常处理-2