异常不同于错误,它是程序运行时产生的未知问题。
如果把程序比喻成一辆汽车,那么汽车开着开着突然前面出现了一个大石头挡住了路,这就叫异常。
那么出现了这个异常我们需要去处理,比如打电话给公路管理局,让它们搬走石头。
如果是汽车的发动机坏了,这叫错误。
即使程序本身没有问题,也会因为各种因素产生异常。
java秉承面向对象的思想,将异常也以类和对象的形式存在。
一、异常类的结构
异常和错误都继承于Throwable,
在Exception和Error下面还有许多具体的子类,这个可以自行查阅文档。
这样将异常类划分详细,便于出现对应异常时,便于编写对应的异常处理语句。
Exception主要是异常类,Error中是错误类。
像下面用到的try {}catch(这里面的类型主要是Exception 类下的子类){}
异常类中也有很多方法,大家可以自行查阅文档。
这里说一个printStackTrace()方法,作用是打印异常的详细信息。
二、在程序中使用异常处理
try{ //可能出现异常的语句 }catch(异常类 异常对象){ //编写异常处理语句 }catch(异常类 异常对象){ //编写异常处理语句 }catch(异常类 异常对象){ //编写异常处理语句 }catch(异常类 异常对象){ //编写异常处理语句 }finally{ //一定会运行到的语句 }
出现异常时:
(1)首先系统会实例化一个异常类的对象,
(2)然后try中自动捕获异常对象
(3)然后跳转到catch语句,逐个匹配最合适的异常类,执行该异常类下的异常处理语句
(4)最后跳转到finally,执行其中的语句。
没有异常时:try中语句执行完后,直接跳转到finally,执行其中的语句。
注:1.一个try{}中只能捕获一个异常。
2.try中当一个语句出现异常后就会跳转到catch,try中该语句之后的语句不会执行。
public class TestException { public static void main(String[] args) { int i = 1, j = 0; try{ int temp = i / j; //此行有问题,j为0,所以在此之后的System.out.println(temp);不会被执行。 System.out.println(temp); }catch(ArithmeticException e){ e.printStackTrace(); }finally{ System.out.println("finally"); //无论异常与否,finally都会执行 } } }
finally
at cn.ch.testException.TestException.main(TestException.java:
3.catch中的异常类顺序要从小到大。
例如有如下继承结构:
写异常处理时可以这样写
public class TestException { public static void main(String[] args) { int i = 1, j = 0; try{ int temp = i / j; System.out.println(temp); }catch(ArithmeticException e){ e.printStackTrace(); //先小类,后大类。
System.out.println("我是Arithmetic异常类,和抛出的异常对象最匹配") //因为捕获到异常后是逐次匹配,把大类(例如Exception)写在前面的话 }catch(RuntimeException e){ //所有异常都是这个大类,后面的异常都是无用的,而且不精确。 e.printStackTrace();
//异常处理语句 }catch(Exception e){ e.printStackTrace();
//异常处理语句 } finally{ System.out.println("finally"); } } }
运行结果: java.lang.ArithmeticException: / by zero at cn.ch.testException.TestException.main(TestException.java:11)
我是Arithmetic异常类,和抛出的异常对象最匹配 finally
三、throws和throw
1.在定义一个方法时,可以使用throws声明,后面加上可能出现的异常类型。
那么这些异常不在该方法中处理,而是交给调用者去处理。
public class TestException { static int add(int x, int y) throws Exception{//此处用throws声明,异常交给调用 return x + y; //的地方去处理。 } public static void main(String[] args) { int a1 = 2; int a2 = 3; try { System.out.println(add(a1, a2));//此处调用了,就必须要处理。 } catch (Exception e) { e.printStackTrace(); } } }
2.throw
利用throw可以人为抛出一个异常,然后try语句进行捕获抛出,然后catch进行匹配。
可知,throw就是将系统自动创建异常对象改为了自己创建异常对象。后面仍然是指catch中
匹配合适的异常类,指向改类中的语句,最后跳转到finally。
唯一的不同就是将系统自动创建改为了人为创建异常对象。
public class TestException { public static void main(String[] args) { try { throw new Exception("自己抛出的异常"); } catch (ArithmeticException e) { //e.printStackTrace(); System.out.println("我是ArithmeticException类异常,和手动抛出的异常类型不匹配"); }catch(Exception e){ e.printStackTrace(); System.out.println("我是Excep类的异常,和手动抛出的异常类型匹配。"); } } }
运行结果:
java.lang.Exception: 自己抛出的异常
我是Excep类的异常,和手段动出的异常类型匹配。
at cn.ch.testException.TestException.main(TestException.java: