1、异常概述
1.1、异常引入
package exception;
public class Excep1 {
public static void main(String[] args) {
int num1 = 1;
int num2 = 0;
//1、num1 / num2 => 1/0
//2、当执行到num1 / num2 因为num2 = 0,程序就会出现(抛出)异常 ArithmeticException
//3、当抛出异常后,程序就退出,崩溃了,下面代码就不会执行
//4、大家想想这样的程序好吗?不好,不应该出现了一个不算致命的问题,就到整个系统崩溃
//5、java程序设计这,提供了 异常处理机制来解决问题;
int res = num1 / num2;
System.out.println("程序继续运行...");
}
}
- 运行结果
1.2、异常入门
- 作用:如果进行异常处理,那么即使程序出现了异常,程序可以继续执行。
- 定义方式:异常处理机制如果认为一段代码可能出现异常/问题,可以使用try-catch异常处理机制来解决
public class ExceptionSource {
public static void main(String[] args) {
int num1 = 1;
int num2 = 0;
//1、num1 / num2 => 1/0
//2、当执行到num1 / num2 因为num2 = 0,程序就会出现(抛出)异常 ArithmeticException
//3、当抛出异常后,程序就退出,崩溃了,下面代码就不会执行
//4、大家想想这样的程序好吗?不好,不应该出现了一个不算致命的问题,就到整个系统崩溃
//5、java程序设计这,提供了 异常处理机制来解决问题;
try {
int res = num1 / num2;
} catch (Exception exception) {
System.out.println(exception.getMessage());
}
System.out.println("程序继续运行...");
}
}
- 运行结果
1.3、异常介绍
-
异常:java语言中,将程序执行中发生的不正常情况称为“异常”
-
异常事件的分类
- Error(错误):java虚拟机无法解决的严重问题;
- Error是严重错误,程序会崩溃;
- Exception(异常):编程错误或偶然的外在原因导致的一般性问题;
- Exception分类:运行时异常和编译时异常;
- Error(错误):java虚拟机无法解决的严重问题;
-
异常类图如下:
2、常见异常 - 运行时异常
2.1、空指针异常
- 空指针异常:NullPointException
- 范例
public class Excep1 {
public static void main(String[] args) {
String name = null;
System.out.println(name.length());
}
}
- 运行异常
2.2、数学运算异常
- 数学运算异常:ArithmeticException
- 范例
public class ExceptionSource {
public static void main(String[] args) {
int num1 = 1;
int num2 = 0;
int res = num1/num2;
}
}
- 运行结果
2.3、数组下标越界异常
- 数组下表越界异常:ArrayIndexOutOfBoundsException
- 范例
public class ExceptionSource {
public static void main(String[] args) {
int[] arr = new int[5];
arr[10] = 7;
System.out.println("end of main() method!");
}
}
- 运行结果
2.4、类型转换异常
-
类型转换异常:ClassCastException
-
范例
public class ExceptionSource {
public static void main(String[] args) {
A b = new B(); //向上转型
B b2 = (B)b; //向下转型
C c2 = (C)b; //抛出异常ClassCastException
}
}
class A{}
class B extends A{}
class C extends A{}
- 运行结果
2.5、数字格式不正确异常
- 数字格式不正确异常:NumberFormatException
- 范例:
public class ExceptionSource {
public static void main(String[] args) {
String name = "离职";
//将String转成int
int num = Integer.parseInt(name); //抛出NumberFormatException
System.out.println(num);
}
}
- 运行结果
3、编译异常
3.1、文件操作
(1)IOEException:操作文件发生异常,由失败或中断的I / O操作产生的一般异常类;
(2)FileNotFoundException:当操作一个不存在的文件时,发生异常;
(3)EOFException:操作文件到文件末尾,发生异常;
3.2、数据库操作
(1)SQLException:查询数据库时,查询表可能发生异常;
3.3、网络波动
(1)java.net.SocketTimeoutException:socket超时错误,超时分为连接超时和读取超时;
(2) java.net.SocketException: Too many open files:指进程打开文件句柄数超过限制,当并发用户数比较大时,服务器可能会报这个异常。
4、异常处理机制
- 1、try - catch - finaly和throws二选一;
- 2、如果没有显式处理异常,则默认是throws;
4.1、try-catch-finally
-
异常处理流程
- 1、发生异常;
- 2、系统将异常封装成Exception对象e,传递给catch;
- 3、得到异常对象后,程序员自行处理,没有发生异常则catch代码块不执行;
- 4、不管try代码块有没有发生异常,始终要执行finally;
- finaly:通常防止要释放资源的代码,比如文件、数据库、网络等的关闭。
-
基本语法
try{
//可疑代码
//将异常生成对应的异常对象,传递给catch块
}catch(异常){
//对异常的处理
}
(1)范例一
public class ExceptionSource {
public static void main(String[] args) {
try { // 检查这个程序的代码
int[] arr = new int[5];
arr[10] = 7; // 这里会出现异常
System.out.println("不发生异常时打印");
}
catch(ArrayIndexOutOfBoundsException e) {
System.out.println("发生异常时执行catck : 数组超出绑定范围!");
}
finally { // 这个程序的代码一定会执行
System.out.println("代码一定会执行 :end of main() method!");
}
}
}
- 运行结果
-
异常处理细节
(1)如果异常发生了,则异常发生后面的代码不会执行,直接进入到catch块;
(2)如果异常没有发生,则顺序执行try的代码块,不会进入catch;
(3)如果希望不管是否发生异常,都执行某块代码块(比如关闭连接,释放资源等),则使用finaly;
(4)如果有多个catch语句,捕获不同的异常(进行不同的业务处理),要求父类异常在后,子类异常在前,发生异常只会匹配一个catch。
因为在用catch捕获异常的时候,会根据catch()中的内容逐个执行,当发现到try中产生的异常和catch内的异常相同时候就会停止。
(2)范例:多catch时,catch异常捕获范围从小到大,只会捕获一次
//1、创建ExampleA类继承异常父类
package exception;
class ExampleA extends Exception{
private String a=null;
//这里必须加上无参的构造函数,因为自己定义了有参的构造函数,则会覆盖原来无参构造函数
//但是子类构造对象时候会先调用父类的构造函数,其中会默认先调用super方法,该方法是调用父类的无参构造函数,若没有定义就会报错
public ExampleA(){}//所以必须写出无参的构造函数,写了有参就要写无参,除非程序不再调用无参的,否则调用就会报错
public ExampleA(String a){
this.a=a;
}
}
//2、创建ExcepleB类继承ExcepleA父类
//当构造对象时候就会默认调用super方法,先调用父类的无参构造函数,super默认调用的
class ExampleB extends ExampleA{
private String b=null;
public ExampleB(String b){
this.b=b;
}
}
//3、创建main方法
//最后的输出仅仅只是Example
public class ExceptionSource {
public static void main(String[] args) {
// TODO Auto-generated method stub
//这里抛出一个ExampleB类对象的一个异常
try {
throw new ExampleB("b");
//这里先catch该父类ExampleA中异常
} catch (ExampleA e) {
//若捕获到就输出EXampleA
System.out.println("捕获父类异常:ExampleA");
//这里数ExampleA的父类,但是这里捕获不到异常new ExampleB(“b”)异常了,因为异常已经被子类ExampleA捕获走了,除非子类捕获不到的异常才会执行捕获
//但是如果先catch父类的异常,子类的异常就会失效,不会执行
} catch (Exception e) {
//所以该catch语句就不会执行了,即不会再输出”Example“
System.out.println("捕获子类异常:ExampleB");
}
}
}
- 运行结果
(3)最佳实践
import java.util.Scanner;
public class ExceptionSource {
public static void main(String[] args) {
//1、创建scanner对象;
//2、使用无限循环,去接受一个输入;
//3、然后将该输入的指,转成一个int
//4、如果在转换时,输出一场,说明输入的内容不是一个可以转成int的内容
//5、如果没有抛出异常,则break该循环
Scanner scanner = new Scanner(System.in);
int num = 0;
String inputStr = "";
while(true){
System.out.println("请输入一个整数:");
inputStr = scanner.next();
try{
num = Integer.parseInt(inputStr); //这里可能抛1出异常
break;
}catch (NumberFormatException e){
System.out.println("请输入的不是整数请重新输入:");
}
}
}
}
- 运行结果
4.2、throws - 默认
-
含义:将发生的异常抛出,交给调用者(方法)来处理,最顶级的处理者就是JVM,JVM输出异常信息之后退出程序;
- 1、如果一个方法(中的语句)可能生成某种异常,但是并不确定如何处理这些异常,则此方法应显示声明抛出异常,表明该方法将不对这些异常进行处理,而由该方法的调用者负责处理
- 2、在方法生命中throws语句可以声明抛出异常的列表,throws后面的异常类型可以是方法中产生的异常类型,也可以是它的父类;
-
特点:
- ①使用throws,抛出异常,让调用f2方法的调用者处理;
- ②throws后面的异常类型可以是方法中产生的异常类型,也可以是它的父类;
- ③throws关键字后也可以是 异常列表,即可抛出多个异常;
-
范例
public class ExceptionSource {
public static void main(String[] args) {
f2();
}
public static void f2() throws ArithmeticException{
int n1 = 10;
int n2 = 0;
double res = n1/n2;
}
}
- 运行结果:f2的异常在被调用时传递给JVM被处理;
- throws异常处理细节
- 对于编译异常,程序中必须处理,比如try-catch 或 throws;
- 对于运行异常,程序中如果没有处理,默认就是throws的方式处理;
- 子类重写父类方法时,对抛出异常的规定:子类重写的方法所抛出的异常类型要么和父类抛出一致,要么为父类抛出的子类型;
- 在throws过程中,如果有方法try-catch,就相当于处理异常,就可以不必throws;
4.3、自定义异常
-
自定义异常:自己设计异常类,用于描述该错误信息
-
语法格式
public class XXException extends Exception|RuntimeException{
添加一个空参数的构造方法
添加一个带异常信息的构造方法
}
- 范例
public class ExceptionSource {
public static void main(String[] args) throws Exception {
if((10+20)==30) {
throw new AddException("错误的相加操作!不允许"); }
}}
class AddException extends Exception{
public AddException(String msg) {
super(msg);
}
}
- 运行结果
4.4、throw和throws的对比
名称 | 意义 | 位置 | 后面跟的东西 |
---|---|---|---|
throws | 异常处理的一种方式 | 方法声明处 | 异常类型 |
throw | 手动生成异常对象的关键字 | 方法体中 | 异常对象 |