1.认识异常
1、异常是指在程序的运行过程中发生的不正常事件,如所需文件找不到、网络连接不通或连接中断、算术运算出错(如被零除)、数组下标越界、装载一个不存在的类、对null对象操作、类型转换异常。
2、异常会中断正在运行的程序。
3、可以通过增加if-else语句对各种异常情况进行判断处理。
4、通过if-else语句进行异常处理,有以下缺点:
-->代码臃肿,加入了大量的异常情况判断和处理代码。
-->程序员把相当多的精力放在了异常处理代码上,放在了“堵漏洞”上,占用了编写业务代码的时间,必然影响开发效率。
-->很难穷举所有的异常,程序仍旧不健壮。
-->异常处理代码和业务代码交织在一起,影响代码的可读性,加大日后程序的维护难度。
5、Java提供了异常处理机制,可以由系统来处理程序在运行过程中可能出现的异常事件,使程序员有更多精力关注于业务代码的编写。
2.Java异常体系结构
1、Java中的异常有很多类型,异常在Java中被封装成了各种异常类。
2、所有异常类都是Throwable类的子类,它派生出两个子类:Error类和Exception类。
Error类:表示仅靠程序本身无法恢复的严重错误,如内存溢出、动态链接失败、虚拟机错误。
应用程序不应该抛出这种类型的错误(一般由虚拟机抛出)。
假如出现这种错误,应尽力使程序安全退出。
在进行程序设计时,应该更关注Exception类。
Exception类:由Java应用程序抛出和处理的非严重错误,如所需文件找不到、网络连接不通或连接中断、算术运算出错(如被零除)、数组下标越界、装载一个不存在的类、对null对象操作、类型转换异常等。
Exception的不同的子类分别对应不同类型的异常。Exception又可以分为两大类异常:
运行时异常:包括RuntimeException及其所有子类。不要求程序必须对它们进行处理。
Checked异常(非运行时异常):除了运行时异常外的其他从Exception类继承来的异常类。
3.Java异常处理机制
3.1 异常处理
1、异常处理机制就像人们对平时可能会遇到的意外情况,预先想好了一些处理的办法;
2、在程序执行代码时,若发生了异常,程序会按照预定的处理办法对异常进行处理,异常处理完毕之后,程序继续运行;
3、Java的异常处理通过5个关键字来实现:try、catch、finally、throw、throws。
3.2 使用try-catch处理异常
Java中提供了try-catch结构进行异常捕获和处理,把可能出现异常的代码放入到try语句块中,并使用catch语句块捕获异常。
public static void main(String[] args) {
//使用异常处理,try-catch结构
try{
Scanner sc=new Scanner(System.in);
System.out.println("请输入被除数:");
int num1=sc.nextInt();
System.out.println("请输入除数:");
int num2 = sc.nextInt();
System.out.println(num1+"/"+ num2 +"="+ num1/ num2);
System.out.println("感谢使用本程序!");
sc.close();
}catch(InputMismatchException e){
System.out.println("输入不匹配异常");
}catch(ArithmeticException e){
System.out.println("算术异常");
}
}
try-catch语句块的执行流程是首先执行try语句块中的语句,这时可能出现以下3种情况:
1.如果try语句块中所有语句正常执行完毕,没有发生异常,那么catch语句块中的所有语句都将会被忽略;
2.如果try语句块在执行过程中发生异常,并且这个异常与catch语句块中声明的异常类型匹配,那么try语句块中剩下的代码都将被忽略,而相应的catch语句将会被执行。匹配是指catch所处理的异常类型与所生成的异常类型完全一致或是它的父类;
3.如果try语句块在执行过程中发生异常,而抛出的异常在catch语句块中没有被声明,那么方法立刻退出。
3.3 使用try-catch-finally处理异常
如果希望try语句块中不管是否发生异常,都执行某些代码,那么就需要在try-catch语句块中加入finally语句块,把要执行的语句放入finally语句块中。
public static void main(String[] args) {
// Try-catch-finally结构
try {
Scanner in = new Scanner(System.in);
System.out.print("请输入被除数:");
int num1 = in.nextInt();
System.out.print("请输入除数:");
int num2 = in.nextInt();
System.out.println(num1 + "/" + num2 + "=" + num1 / num2);
in.close();
return;
} catch (ArithmeticException e) {
System.out.println("产生了算术异常");
return ;
} finally {
System.out.println("感谢使用本程序!");
}
}
无论是否发生异常,finally语句块中的代码总能被执行。try-catch-finally语句块的执行流程大致分为以下两种情况:
1.如果try语句块中所有语句正常执行,finally语句块也会被执行。catch语句块中的代码不会被执行。
2.如果try语句块在执行过程中发生异常,无论这种异常能否被catch语句块捕获到,都将执行finally语句块中的代码。
说明:
1、try-catch-finally结构中的try语句是必须存在的,catch、finally语句为可选,但是两者至少出现其中之一。
2、如果在try语句块或catch语句块中存在return语句,finally语句块中的语句也会执行。发生异常时的执行顺序是:先执行catch语句块中return之前的语句,再执行finally语句块中的语句,最后执行catch语句块中的return语句退出。
3、finally语句块中语句不执行的唯一情况是在try语句块中或者异常处理代码中执行了System.exit(1)退出Java虚拟机。
3.4 使用throws声明抛出异常
如果在一个方法体中抛出了异常,并希望调用者能够及时地捕获异常,Java中通过关键字throws声明某个方法可能抛出的各种异常以通知调用者。
1、throws可以同时声明多个异常,之间用逗号隔开;
2、声明异常是在方法的参数列表后面声明;
3、调用一个声明了异常的方法,可采用如下两种方式进行处理:
-->通过try-catch捕获并处理异常。
-->通过throws继续声明异常。如果调用者不知道如何处理该异常,可以继续通过throws声明异常,让上一级调用者处理异常。main()方法声明的异常将由Java虚拟机来处理。
3.5 使用throw抛出异常
除了系统自动抛出异常外,在编程过程中,有些问题是系统无法自动发现并解决的,比如年龄不再正常范围内,性别输入不是“男”或者“女”等,此时需要程序员而不是系统来自行抛出异常,把问题提交给调用者去解决。在Java语言中,可以使用throw关键字来自行抛出异常。
throwVSthrows
1、作用不同:throw用于程序自行产生并抛出异常;throws用于声明该方法内抛出了异常。
2、使用的位置不同:throw位于方法内部,可以作为单独语句使用;throws必须跟在方法参数列表后面,不能单独试用版。
3、内容不同:throw抛出一个异常表对象,只能是一个;throws后面跟异常类,可以跟多个。
4.自定义异常
(1)当JDK中的异常类型不能满足程序的需要时,可以自定义异常类。
(2)使用自定义异常一般有如下步骤:
1)定义异常类,并继承Exception类或者RuntimeException类。
2)编写异常类的构造方法,并继承父类的实现,常见的构造方法有如下4种形式:
a)构造方法1
public MyException(){
super();
}
b)构造方法2
public MyException(String message){
super(message);
}
c)构造方法3
public MyException(String message,Throwable cause){
super(message,cause);
}
d)构造方法4
public MyException(Throwable cause){
super(cause);
}
3)实例化自定义异常对象,并在程序中使用throw抛出。