Java 中的异常有很多,这种异常机制,可以帮助处理程序中未知的错误。关于异常的处理有try catch 程序块、throw 、throws。
以下分别对这三种进行介绍。
try-catch用来捕获代码段的异常并做出处理
try-catch代码块分两块,第一块是try{} ,第二块是catch(exception的引用){}。
try-catch一般放在循环放外。
try-catch,try即尝试,尝试能不能正常的走完整个作用域,如果不能则抛出一个异常。所以在try块里经常放上可能会抛出异常的程序段。而catch就是处理try里抛出来的异常,其中catch的参数列表接收的是一个异常的引用,是throw抛出来的异常的引用。
try-catch可以嵌套使用,以下是一个try-catch嵌套使用的例子:
public static void main(String[] args) {
try {
System.out.println("**********************外层try**********************");
errorMethod();
} catch (Exception e) {
System.out.println("**********************外层catch" + e + "**********************");
} finally {
System.out.println("**********************外层finally**********************");
}
}
private static void errorMethod() {
try {
System.out.println("**********************内层try**********************");
int i = 0;
int a = 100 / i;
} catch (Exception e) {
System.out.println("**********************内层catch" + e + "**********************");
} finally {
System.out.println("**********************内层finally**********************");
}
}
内层函数体用零作被除数,报ArithmeticException
若是注释掉内层catch,其他一样:
private static void errorMethod() {
try {
System.out.println("**********************内层try**********************");
int i = 0;
int a = 100 / i;
} /*catch (Exception e) {
System.out.println("**********************内层catch" + e + "**********************");
}*/ finally {
System.out.println("**********************内层finally**********************");
}
}
运行结果是:
总结一个报错后的执行顺序:
try {
//A 报错地方
try {
//B
} catch (Exception e) {
//C
} finally {
//D
}
//E
} catch (Exception e) {
//F
} finally {
//G
}
执行顺序:
总结:
1.try-catch 嵌套内层catch 可以捕获异常时,外层catch不会执行,但finally (多用于IO关闭)都会执行。
2.try-catch一般用在最上层的程序里,可以配合throws和throw再将异常抛给用户,这种情况会使上层代码中断。也可以不选择抛出,这种上层代码会继续运行。
3.被调用的方法如果有异常的可能可以通过throws抛给上层处理,不加try catch的情况如下会自动往上抛,加了try catch需要如上通过throw抛给上层程序。
throw 即抛出一个异常,并获取这个异常的引用,这个异常会被抛到外部的环境,由外部环境进行处理。
throw 一般会用于程序出现某种逻辑时程序员主动抛出某种特定类型的异常。
class A{
public void func() throws Exception{
throw new Exception();
}
}
这里抛出了一个Exception,Exception是throwable的子类,是所有异常的基类。与此同时,throwable还有另一个子类,也就是Error。这里会把Exception这个引用抛到外部环境中去处理。
throw跟try...catch...finally的对比:
try catch是直接处理,处理完成之后程序继续往下执行,throw则是将异常抛给它的上一级处理,程序便不往下执行了。
public class ZeroTest {
public static void main(String[] args) {
try{
int i = 100/ 0;
System.out.print(i);
}catch(Exception e){
System.out.print(1);
throw new RuntimeException();
}finally{
System.out.print(2);
}
System.out.print(3);
}
}
上述代码中的catch语句块里面,打印完1之后,又抛出了一个RuntimeException,程序并没有处理它,而是直接抛出,
因此执行完finally语句块之后,程序终止了。
首先执行try,遇到算术异常,抛出,执行catch,打印1,然后抛出RuntimeException,缓存异常,执行finally,打印2,然后抛出RuntimeException。
如果catch中没有抛出RuntimeException,则执行结果为123。
throws并不是抛出一个实际的Exception而是一个异常声明,它声明这个方法可能会抛出一个异常,注意是可能,所以在没有异常的情况下也是可以用throws的,而throws本身的作用也是用来提高程序的健壮性,反过来,如果这个方法的的确有一个异常,那么编译器会强制让加上throws异常声明。
通常throws是写在参数列表的后面,表明这个方法有可能会抛出一个异常。
class A{
public void g() throws Exception{
}
}
区别一:
throw 是语句抛出一个异常;throws 是方法抛出一个异常;
throw语法:throw <异常对象>
throws语法:[<修饰符>]<返回值类型><方法名>([<参数列表>])[throws<异常类>]
在方法声明中,添加throws子句表示该方法将抛出异常。如果一个方法会有异常,但你并不想处理这个异常,就在方法名后面用throws,这样这个异常就会抛出,谁调用了这个方法谁就要处理这个异常,或者继续抛出。其中:异常类可以声明多个,并用逗号分割。
区别二:
throw可以与try-catch-finally语句块一起使用,也可以与throws一起使用。
throws一般单独使用,然后再由处理异常的方法捕获。
联系一:
try .... catch 就是用catch 捕获 try 中某一个操作可能会出现的异常并处理。
throw 不处理异常,而直接抛出异常。throw new Exception()是抛出一个Exception,由其他的method来处理这个Exception。
所以:try....catch是为捕获Exception用的,而throw是抛出Exception让别人去捕获。
如果一个方法中用了throws,那么这个方法会向上抛出一个异常,那么在调用这个方法的时候必须把这个调用放在try...catch块里处理这个异常。
异常的处理方法有两种:
1、声明异常,即在方法名后面加上throws ExceptionName,..., 方法本身只是抛出异常,由函数调用者来捕获异常。若产生异常,异常会顺着调用栈一直找到与之匹配的处理方法,若到达调用栈底仍未找到,就输出异常并终止程序。
2、捕获异常。通过try catch方法,catch子句中放置处理异常的语句。
联系二:
对于可能有异常抛出的程序块,用try{}包住,然后用catch来抓住这个异常,在catch中对异常做处理, 在try中如果有异常的话,程序会转到catch而不会中断。
try和catch只能获取程序运行时引发的异常,而throw语句可以引发明确的异常,程序到了throw语句这后就立即停止,不会执行后面的程序。
本文部分段落摘自以下文章:
https://blog.csdn.net/qq_30715329/article/details/85463461
https://blog.csdn.net/abc19900828/article/details/7889879
https://blog.csdn.net/ztx114/article/details/78251126