1.什么是异常?
在开发过程中难免会出现程序运行不正常的情况,而这些在程序执行过程中出现的不正常情况称为“异常”。
注意:开发过程中,语法的错误和逻辑错误不属于异常。
2. 异常类型
Java 程序中所有的异常都继承自 Throwable 类,Throwable 类有两个子类 Error 类和 Exception 类。在Java开发中主要是对Exception类的操作。
-
Error: Java虚拟机无法解决的严重问题(如堆栈溢出),会导致程序无法正常执行并退出。
一般不编写代码进行处理。
public class ErrorTest { public static void main(String[] args) { //栈溢出: //报错信息:Exception in thread "main"java.lang.StackOverflowError main(args); } }
-
Exception:在程序中因为编程错误或者其他偶然因素出现的(空指针异常、数组下标越界),可以被处理的。 一般编写代码进行处理。
3. Exception
Exception类又分为编译时异常 (检查性异常 checked) 和运行时异常(RuntimeException)
-
编译时异常:在编译过程中必须要进行处理的,否则会编译不通过
-
运行时异常:在编译时无法被检测到,只有执行程序时才会出现的异常,一般系统会自动抛出。
-
常见的异常类型:
编译时异常:
异常类型 | 介绍 |
---|---|
IOException | IO 异常 |
FileNotFoundException | 找不到文件异常,继承自 IO 异常 |
ClassNotFoundException | 找不到类异常 |
运行时异常:
异常类型 | 介绍 |
---|---|
NullPointerException | 空指针异常, 对象不存在 |
ArrayIndexOutOfBoundException | 数组越界异常 |
ArithmeticException | 算术异常, 以0做除数 |
ClassCastException | 类型转换异常 |
InputMismatchException | 输入不匹配异常 |
4. 异常处理
Java编程语言使用异常处理机制为程序提供了错误处理的能力,将可能会产生异常的代码和普通代码分别开来,便于后续的处理和维护。
Java提供的处理机制是一种“抓抛模型”:
-
过程1:抛
程序在执行过程中,一旦出现异常,就会在异常代码处生成一个对应异常类型的对象,并将此对象抛出。如,出现类型转换异常,则生成该类型的对象。
一旦抛出对象后,其后的代码不再执行。
-
过程2:抓
这里的“抓‘’,就是抓住抛出的异常进行处理,也就是异常的处理方式。
Java的异常处理是通过5个关键字来实现的,分别为:
try、catch、finally、throw、throws
4.1异常处理方式
方式1:try-catch-finally
格式:try{
//可能出现异常的代码
}catch(异常类型1 变量名1){
//处理异常的方式1
}catch(异常类型2 变量名2){
//处理异常的方式2
} …
}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); }catch (ArithmeticException e) { System.out.println("除数不能为0"); }catch(InputMismatchException e){ System.out.println("被除数和除数只能是整数"); }catch(Exception e){ System.out.println("产生了一个异常"); }finally{ System.out.println("感谢使用本程序!"); }
异常处理分析:
1)try结构中的代码不会产生异常,那么catch结构的代码就不会执行;
2)try结构中的代码产生了异常,并且catch结构的代码能够处理这个异常,那么catch处理完异常后,程序继续往下执行;
3)try结构中的代码产生了异常,但是catch结构的代码不能处理这个异常,则此时添加finally语句块。无论前面的异常是否可以被处理,都会执行finally内的代码。
4)try后书写多个catch语句块时,按照顺序由上至下,先子类后父类。发生异常时,只执行匹配的第一个catch语句块的代码,其后的catch语句块不执行。
注意:finally语句块中的代码唯一不执行的情况是在前面的try结构或者catch结构中存在退出系统的语句 System.exit(1)。
问题:在try结构中或者catch结构中存在return语句,finally结构里的语句会不会执行?
会执行。try结构或者catch结构中的代码在执行到return语句时,会先去查看有没有finally语句;如果有,输出里面的代码,然后再回到try或者catch结构中执行return语句。
执行步骤如图所示:
方式2:throws + 异常类型
throws + 异常类型 写在方法的声明处,指明该方法执行时可能会出现的异常类型;
在编写的方法体内部,不使用try-catch处理异常,而是在方法的参数列表后 通过 throws 异常类型,将方法内出现的异常抛出,但是并没有处理。谁调用该方法,谁对该方法抛出的异常进行处理。
public static void main(String[] args) throws FileNotFoundException {
**/*当我们调用一个声明了异常的方法(构造方法和普通方法),我们需要去解决这个方法声明的异常,有两种方法解决:
1)继续进行声明,谁调用谁继续声明,main方法声明的异常由Java虚拟机来处理
2)调用产生了异常的方法,可以进行try-catch处理
*/**
FileInputStream fis = new FileInputStream("F://demo.txt");
}
4.2 关于异常对象的产生
1)系统自动生成的异常对象
2)手动的生成一个异常对象,并使用throw抛出
方法内可以手动的创建异常,例如在输入不符合规范时,抛出异常进行提醒
public void setGender(String gender) throws Exception {
this.gender = gender;
throw new Exception("性别只能为男或者女");
}
======================================
Student stu = new Student();
try {
stu.setGender("we");//**当此处输入不符合规范,在setGender方法就会抛出异常**
} catch (Exception e) {
e.printStackTrace();//**抛出的异常进行打印**
}
4.3 自定义异常类
1)继承现有的异常结构:RuntimeException(运行时异常)、Exception(编译时异常);
2)提供一个序列号(serialVersionUID);
3)提供重载的构造器。