目录java
终于完成本学期的最后一门考试,考试周的我,边复习通讯之傅里叶变换,边学习Java的新知识。虽然好久没更,可是私底下的笔记满满,特意总结一波。
总结什么呢?异常!嗯?异常?最近却是人有些异常……复习到一两点,早上早早起来刷题,不异常才怪。异常嘛,很好理解,就是本该正常的事情出了问题嘛。
这时咱们回想咱们以前写过一个再简单不过的例子:计算两个整数相除。二话不说,直接就能够写出以下代码,对吧。编程
public static void main(String[] args) { Scanner input = new Scanner(System.in); System.out.println("Enter two integers: "); int num1 = input.nextInt(); int num2 = input.nextInt(); System.out.println(num1 / num2); }
这短短的代码中就存在着隐患,而这个隐患有可能就会演变成异常。什么状况呢?咱们知道,在Java的整数计算中,若是除数为零,计算式将会是没有任何意义的。带着咱们的猜测,编译运行,不出所料,它飘红了。
学习
因而,咱们对红字进行分析,得出结论:一个名为ArthmeticException的异常在执行main方法的第17行时发生:除数为零。清清楚楚,明明白白。
能够看到,异常一旦发生,程序就将终止,并且这种抛出异常的机制,可以让咱们有效地找到问题所在,并及时解决问题。异常机制的存在,就是为了更好地解决问题,保证程序的健壮性。
因此,咱们试图修改代码,让它在方法中实现:测试
public static int quotient(int num1, int num2) throws ArithmeticException{ if (num2 == 0) { throw new ArithmeticException("Divisor can not be zero"); } return num1 / num2; }
在main方法中调用查看结果:优化
int num1 = input.nextInt(); int num2 = input.nextInt(); try { System.out.println(QuotientWithMethod.quotient(num1, num2)); }catch (ArithmeticException e) { System.out.println(e.getMessage()); }
继续测试(固然为了测试,咱们这里抛出了一个运行时异常,本能够不抛):
指针
throw new ArithmeticException("Divisor can not be zero");
对象。throws ArithmeticException
。try{...}catch (ArithmeticException e){...}
并执行咱们但愿处理异常的语句,System.out.println(e.getMessage());
。固然,上述的例子集抛出异常、声明异常及处理异常于一身,可是异常的内容可不只仅是这么简单,咱们在以后的内容中来探一探异常的究竟:code
先来看一下异常的类继承图,当是不彻底统计的,由于还有还多好多的异常等待着被探索。
对象
经过图片咱们能够明显的发现,这些异常的命名很是好认,果然见名知义。Throwable
是全部异常的顶级父类,在它的下面有两个大类:Exception
和Error
。下面是官方文档对二者进行的解释:blog
合理的应用程序出现的不该该捕获的严重问题 ,合理指的是语法和逻辑上。继承
与虚拟机相关,如系统崩溃、虚拟机错误、动态连接失败等
也叫运行时异常,由Java虚拟机抛出,只是容许编译时不检测,在没有捕获或者声明的状况下也同样可以经过编译器的语法检测,因此不须要去亲自捕获或者声明,固然要抛出该类异常也是能够的。典型的异常类型:Error及其子类异常,RuntimeException及其子类异常。注意:RuntimeException表明的是一类编程错误引起的异常:算数异常、空指针异常、索引越界异常、非法参数异常等等,这些错误若是代码编写方面没有任何漏洞,是彻底能够避免的,这也是不须要捕获或者声明的缘由,也有助于简化代码逻辑。
也叫编译时异常,Java认为受检异常须要在编译阶段进行处理, 必须在显式地在调用可能出现异常的方法时捕获(catch),或者在声明方法时throws异常类型,不然编译不会经过。除了上面提到的Exception及其子类都属于受检异常,固然,不包括上面提到的RuntimeException。
咱们上面提到,咱们没法去直接处理不受检异常,可是咱们必须强制地对可能发生受检异常(编译时异常)的行为作处理,处理方法主要有如下:
public void m1() throws ClassNotFoundException, IOException { //to do something }
try{...}catch{...}
语句捕获,并在catch块中处理该异常。public void m3() { try { m1(); } catch (ClassNotFoundException e) { //to do something } catch (IOException e) { //to do something } }
也能够直接捕获Exception的实例,由于它是这些异常的父类,可是上面的捕获异常引起的错误会更加直接一些。
public void m2() { try { m1(); } catch (Exception e){ //do something } }
若是处理不了,就一直向上抛,直到有完善解决的办法出现为止。固然咱们也能够自行抛出系统已经定义的异常:
public void m2(int i) throws IOException, ClassNotFoundException { if (i >1) throw new IOException("!"); throw new ClassCastException(); }
须要注意的是:
咱们知道,程序发生错误时,系统会自动抛出异常。那么,咱们若是想独家定制一个属于本身的异常能够不?答案显然是能够的,情人节快到了,直接自定义一个异常:
class noGirlFriendException extends Exception{ noGirlFriendException(){ } noGirlFriendException(String msg){ super(msg); } }
须要注意的是:
//下面的形式错误! public static void main(String[] args) { try { System.out.println(1 / 0); } catch (Exception e) { e.printStackTrace(); } catch (ArithmeticException e) { System.out.println(e.getMessage()); } }
try { System.out.println(1 / 0); } catch (ArithmeticException | NullPointerException e) { //捕获多异常时,异常变量被final隐式修饰 //!false: e = new ArithmeticException(); System.out.println(e.getMessage()); }
本文参考诸多资料,并加上自身理解,若有叙述不当之处,还望评论区批评指正。关于异常,还有一部份内容,下篇进行总结,晚安。
参考资料:
https://stackoverflow.com/questions/6115896/understanding-checked-vs-unchecked-exceptions-in-java
https://www.programcreek.com/2009/02/diagram-for-hierarchy-of-exception-classes/