Day015 异常处理机制
异常处理机制
-
抛出异常
-
捕获异常
-
异常处理的五个关键字
- try:监控一个代码块,有异常就能通过catch捕获
- catch(想要捕获的异常类型):捕获想要捕获的异常,catch代码块的代码只有在捕获到异常才执行
- finally:处理善后工作。不管有没有捕获到异常,finally代码块的代码都会执行
- throw用来抛出一个具体的异常类型(用在方法体中,使用throw一定会抛出一个异常)
- throws用来声明一个方法可能产生的所有异常,不做任何处理而是将异常往上传,谁调用我我就抛给谁。(用在方法声明后面,表示可能会抛出异常,不一定会抛出)**
如何抛出和捕获异常
首先,我们来先看一个异常
public static void main(String[] args) {
int a=1;
int b=0;
System.out.println(a/b);
}
输出结果
Exception in thread "main" java.lang.ArithmeticException: / by zero
用try catch捕获这个异常
public static void main(String[] args) {
int a = 1;
int b = 0;
try {
System.out.println(a / b);
} catch (ArithmeticException e) {
System.out.println("程序出现异常:"+e);
} finally {
System.out.println("finally");
}
}
输出结果
程序出现异常:java.lang.ArithmeticException: / by zero
finally
接下来我们把b改为1试一下
public static void main(String[] args) {
int a = 1;
int b = 1;
try {
System.out.println(a / b);
} catch (ArithmeticException e) {
System.out.println("程序出现异常:" + e);
} finally {
System.out.println("finally");
}
}
输出结果:
1
finally
- 可以发现如果没有捕获到异常,catch代码块是不会执行的,而finally代码块不管有没有捕获到异常都会执行。
- 通常try和catch一起使用,finally可以不要,finally最常用在一些I/O流、资源类的使用后的关闭工作。
接下来,我们再看一个异常
public class Test {
public static void main(String[] args) {
new Test().a();
}
public void a(){
b();
}
public void b(){
a();
}
}
输出结果
Exception in thread "main" java.lang.StackOverflowError
因为a调b,b调a,程序陷入死循环,最终导致栈溢出了,接下来我们用上面的方式捕获异常
public class Test {
public static void main(String[] args) {
try {
new Test().a();
} catch (ArithmeticException e) {
System.out.println("程序出现异常:" + e);
} finally {
System.out.println("finally");
}
}
public void a(){
b();
}
public void b(){
a();
}
}
输出结果
finally
Exception in thread "main" java.lang.StackOverflowError
可以发现没有捕获到异常,这是因为这个异常不是ArithmeticException,而是StackOverflowError,所以当然就捕获不到,接下来回顾一下异常类
我们知道了这是个栈溢出异常,要用StackOverflowError或者它的父类来捕获,假设我不知道它会抛出什么异常,我直接用异常的超类Throwable捕获也是可以的。
public class Test {
public static void main(String[] args) {
try {
new Test().a();
} catch (Throwable e) {
System.out.println("程序出现异常:" + e);
} finally {
System.out.println("finally");
}
}
public void a(){
b();
}
public void b(){
a();
}
}
输出结果
程序出现异常:java.lang.StackOverflowError
finally
捕获多个异常
还是上面的例子,这次我们捕获多个异常,我们知道Error和Throwable都能捕获到异常
public class Test {
public static void main(String[] args) {
try {
new Test().a();
} catch (Exception e) {
System.out.println("Exception捕获:" + e);
} catch (Error e) {
System.out.println("Error捕获:" + e);
} catch (Throwable e) {
System.out.println("Throwable捕获:" + e);
} finally {
System.out.println("finally");
}
}
public void a() {
b();
}
public void b() {
a();
}
}
输出结果:
Error捕获:java.lang.StackOverflowError
finally
我们发现只被Error捕获,多个catch最终只有一个catch捕获到异常,接下来我们把Error和Throwable调换一下
public class Test {
public static void main(String[] args) {
try {
new Test().a();
} catch (Exception e) {
System.out.println("Exception捕获:" + e);
} catch (Throwable e) {
System.out.println("Throwable捕获:" + e);
} catch (Error e) {//编译报错了Exception 'java.lang.Error' has already been caught
System.out.println("Error捕获:" + e);
} finally {
System.out.println("finally");
}
}
public void a() {
b();
}
public void b() {
a();
}
}
直接编译报错了Exception ‘java.lang.Error’ has already been caught,因为我们已经通过Throwable先捕获异常了,而Error是Throwable的子类,所以这个Error的catch永远不会被执行。因此捕获多个异常应该按从小(异常子类)到大(异常父类)的顺序捕获。
快速捕获异常快捷键
- 选中需要捕获异常的代码,ctrl+alt+t
throw主动抛出异常
我们程序中一些我们已经预知的异常,我们可以通过throw主动抛出
以第一个异常为例,我们都知道除数为0肯定是异常,我们就可以自己抛出
public static void main(String[] args) {
int a=1;
int b=0;
try {
if(b==0){
throw new ArithmeticException("除数为0");//主动抛出异常
}
System.out.println(a/b);
} catch (Exception e) {
e.printStackTrace();
} finally {
}
}
输出结果
java.lang.ArithmeticException: 除数为0
at com.dwy.exception.Test2.main(Test2.java:10)
throws抛出异常
我们写一个打印两个数相除的结果的方法
public class Test3 {
public static void main(String[] args) {
int a=1;
int b=0;
try {
new Test3().printDivide(a,b);
} catch (ArithmeticException e) {
e.printStackTrace();
}
}
//打印两个数相除的结果
public void printDivide(int a,int b) throws ArithmeticException{
System.out.println(a/b);
}
}
输出结果
java.lang.ArithmeticException: / by zero
at com.dwy.exception.Test3.printDivide(Test3.java:17)
at com.dwy.exception.Test3.main(Test3.java:9)
在printDivide函数捕获到异常时,会抛到调用该函数的方法中,在该方法中进行捕获处理。