在开发程序过程中,异常是大家都遇到过的一种状况,异常和bug还有一些区别,bug通过是指程序逻辑上的错误,导致运行结果和预期不一致,而异常则不是,它的存在可能导致程序的崩溃,因此我们非常有必要处理好它。
1、异常基本情况
public class ExceptionDemo {
public static void main(String[] args) {
System.out.println("************ 计算开始 ************");
int i = 10;
int j = 0;
int temp = i/j;
System.out.println("两数相除:" + temp);
System.out.println("************ 计算结束 ************");
}
}
// 运行结果
************ 计算开始 ************
Exception in thread "main" java.lang.ArithmeticException: / by zero
at FirstJavaDemo.main(FirstJavaDemo.java:49)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)
这里报了一个除数是0的异常,程序中断执行。
2、处理异常
对于上面的异常,我们应该怎么处理呢?Java里有专门的关键字来捕获和处理异常
public class ExceptionDemo {
public static void main(String[] args) {
System.out.println("************ 计算开始 ************");
int i = 10;
int j = 0;
try {
int temp = i/j; // 这里会出现异常
System.out.println("两数相除:" + temp); // 异常之后的代码不执行
System.out.println("---------------------------------"); // 异常之后的代码不执行
}catch (ArithmeticException e){ // 捕获算术异常
System.out.println("出现异常:" + e); // 出现异常执行异常处理的语句
}
System.out.println("************ 计算结束 ************");
}
}
// 运行结果
************ 计算开始 ************
出现异常:java.lang.ArithmeticException: / by zero
************ 计算结束 ************
这里我们看到是出现并捕获了一个异常,那如果出现多个不同类型的异常该怎么办?
例如,我们让用户通过界面输入两个整数a,b,程序返回a,b相除的结果。
这里看似很简单,但是可能存在的异常有三个
- 输入的参数个数是否恰好是两个
- 输入的参数是否都是整数
- 第二个参数是否是0
public class ExceptionDemo {
public static void main(String[] args) {
System.out.println("************ 计算开始 ************");
int i = 0;
int j = 0;
try {
String arg1 = args[0]; // 接收第一个参数
String arg2 = args[1]; // 接收第二个参数
i = Integer.parseInt(arg1);
j = Integer.parseInt(arg2);
int temp = i/j;
System.out.println("两数相除:" + temp);
System.out.println("---------------------------------");
}catch (ArithmeticException e){
System.out.println("算术异常:" + e);
}catch (NumberFormatException e){
System.out.println("字符转换异常:" + e);
}catch (ArrayIndexOutOfBoundsException e){
System.out.println("数组越界异常:" + e);
}
System.out.println("************ 计算结束 ************");
}
}
异常类的继承结构
整个Java的异常结构中,有两个最常用的类:Exception、Error,这两个都是Throwable的子类。
- Exception: 一般表示程序中出现的问题,可以用 try…catch 处理
- Error:一般指JVM错误,程序中无法处理
3、Java的异常处理机制
在整个java的异常处理中,实际也是按照面向对象的方式进行处理,步骤如下:
- 一旦产生异常,会自动实例化一个异常类对象
- 在try语句中对异常对象进行捕获
- 产生的异常对象与catch语句中的异常进行匹配,匹配上了则执行catch中的代码。
虽然可以写多个catch捕获多个类型的异常,但是不可能遍历全部异常,那这种情况该怎么处理?我们可以最后再加一个catch捕获其它通类异常。
public class ExceptionDemo {
public static void main(String[] args) {
System.out.println("************ 计算开始 ************");
int i = 0;
int j = 0;
try {
String arg1 = args[0]; // 接收第一个参数
String arg2 = args[1]; // 接收第二个参数
i = Integer.parseInt(arg1);
j = Integer.parseInt(arg2);
int temp = i/j;
System.out.println("两数相除:" + temp);
System.out.println("---------------------------------");
}catch (ArithmeticException e){
System.out.println("算术异常:" + e);
}catch (NumberFormatException e){
System.out.println("字符转换异常:" + e);
}catch (ArrayIndexOutOfBoundsException e){
System.out.println("数组越界异常:" + e);
}catch (Exception e){ // 捕获更粗的异常应该放在更细的异常之后
System.out.println("其它异常:" + e);
}
System.out.println("************ 计算结束 ************");
}
}
总结一下
1、异常会让程序报错,不能执行,需要进行处理
2、用try…catch或者try…catch…finally 捕获异常,不管是否捕获到异常,finally是一定会执行
3、一个异常处理中可以有多个catch,而且捕获粒度大的异常应该放在捕获更细的异常之后,
4、捕获的时候可以直接捕获Exception,但最好还是分开捕获,如果是统一处理的话这样也可以。
5、每次产生异常,会在程序中实例化一个异常类对象,然后这个对象会和catch中的异常类型进行匹配,匹配上了则执行catch中的代码,否则继续向下匹配,如果都匹配不到,则程序出现执行中断问题。