文章目录
1. 异常的概念与体系结构
- 异常的处理
- 总结
1. 异常的概念与体系结构
1.1 异常的概念
什么是异常呢?
在java中,将程序执行过程中发生的不正常行为称为异常
java中不同类型的异常,都有与其对应的类来进行描述
接下来看看有哪些常见的异常:
- 算术异常
public class Test {
public static void main(String[] args) {
System.out.println(10/0);
}
}
- 数组越界异常
public class Test {
public static void main(String[] args) {
int[] arr = {0,1,2,3};
System.out.println(arr[100]);
}
}
- 空指针异常
public class Test {
public static void main(String[] args) {
int[] arr = null;
System.out.println(arr.length);
}
}
- 输入不匹配异常
import java.util.Scanner;
public class Test {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
System.out.println(n);
}
}
1.2 异常的体系结构
1.3 异常的分类
- 编译时异常
在程序编译期间发生的异常,称为编译时异常,也称为受检查异常(Checked Exception)
程序想要编译,必须处理异常后才能继续编译
class Person{
private String name;
private String gender;
int age;
//想要让该类支持深拷贝,覆写Object类的clone方法即可
public Person clone(){
return (Person)super.clone();
}
}
- 运行时异常
- 异常的处理
异常处理主要的5个关键字:throw、try、catch、final、throws
2.1 抛出异常throw
在Java中,可以借助throw关键字,抛出一个指定的异常对象,将错误信息告知给调用者。具体语法如下
throw new XXXException("异常产生的原因");
接下来我们写一个抛出异常的代码
public class Test {
public static void main(String[] args) {
int[] arr = null;
test(arr);
}
public static void test (int[] arrays){
if(arrays == null){
throw new NullPointerException("传递的数组为null");
}
}
}
2.2 异常的捕获(throws 以及try-catch)
异常的捕获,也就是异常的具体处理方式,主要有两种:异常声明throws 以及 try-catch捕获处理
异常声明throws
语法格式:
修饰符 返回值 类型 方法名(参数列表) throws 异常类型1,异常类型2...{
//...
}
public class Test {
public static void main(String[] args) throws Exception {
int[] arr = null;
test(arr);
}
public static void test(int[] arrays) throws Exception{
if(arrays == null){
throw new NullPointerException();
}
}
}
try-catch捕获并处理
语法格式:
try {
//将可能出现异常的代码放在这里
//可能会抛出异常,也可能不会
}catch(要捕获的异常类型 e){
//如果try中的代码抛出异常了,此处catch捕获时异常类型与try中抛出的异常类型一致时,或者是try中抛出异常的基类时,就会被捕获到
//对异常就可以正常处理,处理完成后,跳出try-catch结构,继续执行后序代码
}
注意事项:
- try块内抛出异常位置之后的代码将不会被执行
public class Test {
public static void main(String[] args) throws Exception {
try {
int[] arr = null;
System.out.println(arr[3]);
System.out.println("hello world");
} catch (NullPointerException e) {
e.printStackTrace();
}
}
}
没有输出hello world
- 如果抛出异常类型与catch时异常类型不匹配,即异常不会被成功捕获,也就不会被处理,继续往外抛,直到JVM收到后中断程序----异常是按照类型来捕获的
抛出异常类型与catch时异常类型不匹配:
public class Test {
public static void main(String[] args) throws Exception {
try {
int[] arr = null;
System.out.println(arr[3]);
System.out.println("hello world");
} catch (ArithmeticException e) {
e.printStackTrace();
}
}
}
- try中可能会抛出多个不同的异常对象,则必须用多个catch来捕获----即多种异常,多次捕获
public class Test {
public static void main(String[] args) throws Exception {
try {
int[] arr = null;
System.out.println(arr[3]);
System.out.println("hello world");
} catch (ArithmeticException e) {
e.printStackTrace();
} catch (NullPointerException e){
e.printStackTrace();
} catch (ArrayIndexOutOfBoundsException e){
e.printStackTrace();
}
}
}
多个异常的处理方式是完全相同, 也可以写成这样:
public class Test {
public static void main(String[] args) throws Exception {
try {
int[] arr = null;
System.out.println(arr[3]);
System.out.println("hello world");
} catch (ArithmeticException | NullPointerException |ArrayIndexOutOfBoundsException e) {
e.printStackTrace();
}
}
}
异常之间具有父子关系,一定是子类异常在前catch,父类异常在后catch,否则语法错误
public static void main(String[] args) throws Exception {
try {
int[] arr = null;
System.out.println(arr[3]);
System.out.println("hello world");
} catch (ArithmeticException | NullPointerException |ArrayIndexOutOfBoundsException e) {
e.printStackTrace();
} catch (Exception e){
e.printStackTrace();
}
}
Exception可以捕获到所有异常
finally
有些特定的代码,不论程序是否发生异常,都需要执行;在程序正常或者异常退出时,必须要对资源进进行回收;异常还可能会引发程序的跳转,可能导致有些语句执行不到,就需要用到finally这个关键字了
语法格式
try {
//...
}catch(要捕获的异常类型 e){
//...
}finally{
//此处的语句无论是否发生异常,都会被执行到
//如果没有抛出异常,或者异常被捕获处理了,这里的代码也会执行
}
public static void main(String[] args) throws Exception {
try {
int[] arr = null;
System.out.println(arr[3]);
} catch (ArithmeticException | NullPointerException |ArrayIndexOutOfBoundsException e) {
e.printStackTrace();
} finally {
System.out.println("hello world");
}
}
- 总结
一个程序先执行 try 中的代码,如果 try 中的代码出现异常, 就会结束 try 中的代码, 看和 catch 中的异常类型是否匹配。如果找到匹配的异常类型,就会执行 catch 中的代码。如果没有找到匹配的异常类型,就会将异常向上传递到上层调用者。无论是否找到匹配的异常类型,finally 中的代码都会被执行到(在该方法结束之前执行)。如果上层调用者也没有处理异常, 就继续向上传递直到 main 方法也没有合适的代码处理异常, 就会交给 JVM 来进行处理,此时程序就会异常终止。