Java中提供异常(exception)的概念,用来刻画程序逻辑中的非正常情况,是构成逻辑流程的必要因素。
使用异常形式的优点:
(1)增强程序的逻辑可读性
(2)增加调用上的友好性
Java异常处理机制
Java对于异常处理的方式有两种:一种是使用try-catch捕获并处理,称为主动异常处理技术;另一种是不处理,而将异常抛给上一层调用者,由方法调用者负责处理异常,称为被动处理技术。
处理异常的关键字
Java处理异常的关键字有五个关键字:try,catch,throw,throws,finally。
主动异常处理语句包括三部分:try语句块,catch语句块和finally语句块。
其中try语句块界定可能产生异常的语句部分;
catch语句块是在异常发生时,对异常进行处理的部分,每个catch语句块处理一种异常情况,异常情况的类型通过catch后面的异常语句类型来界定;
一个try语句块可以附带多个catch语句块,分别针对不同的异常情况;
finally语句块为try-catch语句块提供一个统一的出口,使得在程序流转到其他部分之前,无论是否产生异常,都能对程序状态进行统一管理,即finally语句中的内容在任何情况下都必须被执行。
Java异常处理的优点:
(1)把错误代码与常规代码分离开
(2)可以在catch里面传播异常信息
(3)可以对异常类型分组
(4)方便定位异常并维护
异常的分类
异常的处理过程
Java处理异常的流程控制语句有:
try-catch语句
多重catch语句
try-catch-finally语句
还有throws,throw关键字可以使用
try-catch语句
try-catch语句的基本格式为:
try {
...
}catch(ExceptionType1 name1){
...
}catch(ExceptionType2 name2) {
...
}
其中catch语句可以有一个或者多个,而且至少要有一个catch语句。
catch语句中的参数类似于方法的声明,包括一个异常类型和一个异常对象。异常类型必须为Throwable类的子类,它指明了catch语句所处理的异常类型,异常对象则是由运行时系统在try所指定的代码块中生成并被捕捉,大括号中包含对异常的处理,其中可以调用异常对象的方法。
catch语句可以有多个,分别处理不同类型的异常。Java运行时系统自上而下分别对每一个catch语句处理的异常类型进行检测,直到找到类型相匹配的catch语句为止。类型匹配是指catch所处理的异常类型与生成的异常对象的类型完全一致或者是它的父类。
package Liu;
class Abc {
public int x;
public int y;
}
public class Trycatch {
public static void main(String[] args) {
// TODO Auto-generated method stub
int z;
String County [] = {"China","Japan","India"};
try {
Abc a = new Abc();
a.x = 0;
a.y = 0;
if(a.y == 0) {
z = 3/a.y;
}else {
for(int i=0;i<5;i++) {
System.out.println(County[i]);
}//for
}//else
}catch (ArithmeticException name1) {
System.out.println("divede by zero error!");
}catch (ArrayIndexOutOfBoundsException name2) {
System.out.println("array error!");
}catch (Exception name3) {
System.out.println("error!");
}
}
}
divede by zero error!
异常列表的顺序是关键的,通常把最容易发生的异常情况放在异常列表的前面,而所有异常的父类Exception放在最后。因为发生异常的时候,系统匹配异常的类型都是由上到下的。
finally语句
finally是对Java异常处理流程的最佳补充。无论是否有异常发生,finally语句块的代码总会被执行。使用finally语句块可以维护对象的内部状态,并可以清理非内存资源。
finally语句块必须和try或者try-catch配合使用,从理论上讲,如果finally块存在,则它总会被执行。但是也可以有一种方法退出try块而不执行finally块,即在try内部代码执行System.exita(0)应用程序终止,而不会执行finally。
try-catch-finally程序块中的return
写在try或者catch中的return语句也就不会真正的从该函数中跳出,它的作用在这种情况下就变成将控制权转到finally语句块中。
例如,在try或者catch语句中存在return false语句,而在finally语句中存在return true语句,那么这种情况下上级调用方法不能获取try或者catch中的返回值false,而是获取finally中的返回值true,由此可见try或者catch中的return语句只是起到转移控制权的作用。
package Liu;
class TestReturn {
public String pb() {
try {
int array[] = {1,2,3};
for(int i=0;i<4;i++) {
int b = array[i];
}
}catch (ArrayIndexOutOfBoundsException e) {
System.out.println("异常:数组越界");
return "aaaa";
}finally {
System.out.println("finally语句已经被执行");
return "bbbb";
}
}
}
public class Test {
public static void main(String[] args) {
TestReturn return1 = new TestReturn();
String s = return1.pb();
System.out.println(s);
}
}
异常:数组越界
finally语句已经被执行
bbbb
由程序运行结果可以看出,pb()的返回值是“bbbb”,而且是在执行finally之后返回的,这就说明catch块中的return语句没有被执行,只是起到转移控制权的作用。
throws
单词throws为“投,掷,扔,抛”的意思。关键字throws用来标明一个方法可能抛出的各种异常。大多数异常处理程序采用主动抛出异常机制的方式,而throws是一种被动异常处理机制。本质上,throws并没有将异常进行处理,而是将“处理责任”推卸给它的上层调用者。比如日常生活中的例子:发生火灾,人群自行扑灭,解决不了就拨打119通知消防。
异常不能被回避,但是通过throws机制能够将一些异常集中到一个地方处理,能够增加程序的可维护性。
在这里插入代码片
throw
在程序中使用throw语句来抛出异常称为直接抛出异常。该异常可以在程序中进行捕获和处理,也可以交给该方法的调用者来捕获和处理。程序会在throw语句处停止,并转向try-catch寻找异常处理的方法,而不再执行throw以后的语句。
…
自定义异常
Java可以让代码开发者自行创建异常和异常类,使系统能够识别这种错误并进行处理。自定义异常不可能依靠系统自动抛出,而必须通过throw语句抛出,通常是通过条件判断来确定是否抛出。
package Liu;
import java.util.Scanner;
//自定义异常类InputException
class InputException extends Exception {
//无参数构造方法
public InputException() {
}
//带参数继承父类构造方法
public InputException(String s) {
super(s);
}
}
//测试类
public class Test {
public static void main(String[] args) {
try { //输入长和宽并判断是否在范围内
Scanner scanner = new Scanner(System.in);
int length = scanner.nextInt();
int width = scanner.nextInt();
if(length<=3||length>=10||width<=2||width>=6) {
//不在范围内抛出InputException异常,带参数实例化
throw new InputException("输入的数值不在指定范围内,请输入[3.10]的length和[2,6]的width值!");
}
//正确输入则输出面积
System.out.println("面积为:" + length * width);
}catch (NullPointerException e) { //捕捉NullPointerException异常
System.out.println("输入的是字符,请输入数字!");
}catch(InputException gException) { //捕捉InputException异常
System.out.println(gException.getMessage());
}
}
}
程序运行结果
4
3
面积为:12
49
7
输入的数值不在指定范围内,请输入[3.10]的length和[2,6]的width值!