一、异常处理及catch的顺序
catch块跟在try语句后面,它可以是一个或多个;catch块有一个参数,该参数是某种异常类的对象;多重catch语句中,异常类型必须子类在前父类在后;try语句块不可以独立存在,必须与catch或者finally块共存
语法
try{
//一些会抛出异常的方法
}catch(Exception e){
//处理该异常的代码块
}catch(Exception2 e){
//处理Exception2的代码块
}...(n个catch块)...{
}finally{
//最终将要执行的一些代码
}
示例
下面的类给出了divider(除数),result(结果),利用try-catch捕获while循环。每次循环,divider减一,result=result+100/divider。如果捕获异常,打印输出“抛出异常了!!!”,返回-1;否则返回result
package com.exer.mytest;
public class TryCatchTest{
public static void main(String[] args){
TryCatchTest tct = new TryCatchTest();
int result = tct.test();
System.out.println("test()方法执行完毕,返回值为:"+result);
}
public int test(){
int divider = 10;
int result = 100;
try{
while(divider > -1){
divider--;
result = result + 100/divider;
}
return result;
}catch(Exception e){
e.printStackTrace();//打出抛出异常的具体信息
System.out.println("循环抛出异常了!!!");
return -1;
}
}
}
运行结果:
循环抛出异常了!!!
test()方法执行完毕,返回值为:-1
java.lang.ArthmeticException:/by zero
at com.exer.mytest.TryCatchTest.test(TryCatchTest.java:17)
at com.exer.mytest.TryCatchTest.main(TryCatchTest.java:7)
public static void main(String[] args){
TryCatchTest tct = new TryCatchTest();
int result = tct.test();
System.out.println("test()方法执行完毕,返回值为:"+result);
int result2 = tct.test2();
System.out.println("我想大声告诉你!test2()方法执行完毕!!");
}
public int test2(){
int divider = 10;
int result = 100;
try{
while(divider > -1){
divider--;
result = result + 100/divider;
}
return result;
}catch(Exception e){
//e.printStackTrace();//打出抛出异常的具体信息
System.out.println("循环抛出异常了!!!");
return result = 999;
}finally{
System.out.println("这是finally!!哈哈!!");
System.out.println("我是Result!!我的值是:"+result);
}
}
运行结果:
循环抛出异常了!!!
这是finally!!哈哈!!
我是Result!我的值是:999
我想大声告诉你!test2()方法执行完毕!!
从以上例子中可以看出,finally块是在try块和catch块执行完成之后,返回到调用者之前会执行的。
public static void main(String[] args){
TryCatchTest tct = new TryCatchTest();
int result = tct.test3();
System.out.println("我想大声告诉你!test3()方法执行完毕!!~返回值为:"+result);
}
public int test3(){
int divider = 10;
int result = 100;
try{
while(divider > -1){
divider--;
result = result + 100/divider;
}
}catch(Exception e){
//e.printStackTrace();//打出抛出异常的具体信息
System.out.println("循环抛出异常了!!!");
}finally{
System.out.println("这是finally!!哈哈!!");
System.out.println("我是Result!!我的值是:"+result);
}
System.out.println("我是test3!我运行完了!表想我");
return 1111;
}
运行结果:
循环抛出异常了!!!
这是finally!!哈哈!!
我是Result!我的值是:381
我是test3!我运行完了!表想我
我想大声告诉你!test3()方法执行完毕!!~返回值为:1111
二、异常抛出
Java中的异常抛出会用到throw和throws。throws声明将要抛出何种类型的异常,是一个声明,throw指将产生的异常抛出,是一个动作。如果某个方法调用到了会抛出异常的方法,那么必须添加try-catch语句去尝试捕获这种异常,或者添加throws声明,来将异常抛出给更上一层的调用者去进行处理。
自定义异常是自己定义的异常类型,但这个自定义异常类必须继承Java标准异常库中意思相近的异常类型,或者直接继承所有异常类型的基类,即Exception类型。
例如
public calss DrunkException extends Exception{
public DrunkException(){
}
public DrunkException(String message){
super(message);
}
}
三、异常链
有时候,可以把捕获的异常包装成一个新的异常,然后在新的异常里面添加对原始异常的引用,再把新异常抛出,就像是链式反应一样。
public class ChainTest(){
public static void main(String[] args){
ChainTest ct = new ChainTest();
try{
ct.test2();
}catch(Exception e){
e.printStackTrace();
}
}
public void test1() throws DrunkException{
throw new DrunkException("喝酒别开车!");
}
public void test2(){
try{
test1();
}catch(DrunkException e){
RuntimeException newExc = new RuntimeException("司机一滴酒,亲人两行泪~~");
newExc.initCause(e);
throw newExc;
}
}
}
test2()另一种写法
```Java
public void test2(){
try{
test1();
}catch(DrunkException e){
RuntimeException newExc = new RuntimeException(e);
//newExc.initCause(e);
throw newExc;
}
}
小结:
- 处理运行时异常时,采用逻辑去合理规避同时辅助try-catch处理
- 在多重catch块后面,可以加一个catch(Exception)来处理可能会被遗漏的异常
- 对于不确定的代码,也可以加上try-catch,处理潜在的异常
- 尽量去处理异常,切忌只是简单的调用printStackTrace()去打印输出
- 具体如何异常,要根据不同的业务需求和异常类型去决定
- 尽量添加finally语句块去释放占用的资源