当运行时发生的错误就是异常,而不是编译时发生的语法错误。比如下面:
class Computer{ void count(int i, int j) { System.out.println("两个数的商是:" + i / j); }} class Exceptions{ public static void main(String[] args) { Computer c=new Computer(); c.count(8,0); //算数错误 }}
代码没有语法错误,可以编译通过。但运行却出错,因为不能用0做除数。
Java中的错误处理通过异常处理模型完成。异常必须被捕获,否则将如上图,程序会终止。
Java中发生异常时会创建表示该异常的实例,其中包含了有关信息,我们可以在方法中调用该实例。
异常
说明
Exception
异常根类
ArithmeticException
算数错误
IllegalArgumentException
方法接收到非法参数
ArrayIndexOutOfBoundsException
索引超出数组长度
NullPointerException
尝试访问null对象
ClassNotFoundException
不能加载所需的类
NumberFormatException
字符串到float数字转换无效
IOException
IO异常根类
FileNotFoundException
找不到文件
EOFException
文件结束
InterruptedException
线程中断
一. try…catch… :
只要程序中可能发生异常,我们就要预防,如除法中除数误设为0。要做到防患于未然,须要使用try和catch,试着在运行的时候捕获意外状况。
class Computer{ void count(int i, int j) { try{ System.out.println("两个数的商是:" + i / j); }catch(Exception e){ System.out.println("Java异常说明:"+e.toString()); } System.out.println("异常处理结束"); }} class Exceptions{ public static void main(String[] args) { Computer c=new Computer(); c.count(8,0); }}
异常说明捕获到的是ArithmeticException,所以我们可以直接在catch中捕获这个异常,而不是根异常类。异常还有个printStackTrace方法,可以返回在代码中的相关信息。
二. finally:
当警察抓小偷,抓到了要汇报,抓不到也要汇报。汇报这个工作是一定要做的,在异常处理中就用finally来完成。无论catch是否捕获了异常,总会执行finally语句块。
第二次编译时将除数设置为1,finally语句块仍旧打印了出来。
三. 多重catch:
如果有个汪洋大盗,很厉害。我们派一个菜鸟捕头去抓未必能抓得到,因为菜鸟捕头擅长的是抓地痞流氓;所以我们再派一个大虾捕头去,他一出马,基本上任何非法分子都跑不掉。
class Computer{ void count(int i, int j) { try{ System.out.println("两个数的商是:" + i / j); }catch(NumberFormatException nfe){ System.out.println("菜鸟抓到啦"+nfe.toString()); nfe.printStackTrace(); }catch(Exception e){ System.out.println("大侠抓到啦"+e.toString()); e.printStackTrace(); }finally{ System.out.println("无论谁抓到,都是我请功"); } System.out.println("抓捕结束"); }} class Exceptions{ public static void main(String[] args) { Computer c=new Computer(); c.count(8,0); }}
菜鸟NumberFormatException先出马,搞定了,大虾Exception就不必劳烦,没搞定,就算累死,还得靠大虾。如果是大虾先上,一定的,菜鸟只能去街上抓小鱼小虾了,优哉游哉啊。但是我感觉虽然代码上大虾先出马就几行英文,但在程序运行上可能会兴师动众的,所以菜鸟能搞定的就让菜鸟先上。
上个例子也不合适,因为NumberFormatException不是用来捕获算数异常的。为了演示。让对的人做对的事才对。
四. 嵌套try… catch… :
我们做某事以前可能有意外,但我们干这件事时也可能还会造成新的意外。此时需要嵌套捕获异常。比如我们获取一个数字,让它作为除数得到另一个数。可能我们获取到一个数字,但它是0;也有可能没获取到数字,是一个字母。
class Computer{ void count(String[] arr) { //先捕获是否为数字的异常 try{ //再捕获除数为0的异常 try{ int dividend=Integer.parseInt(arr[0]); //被除数。将数组元素转为数字 int divisor=Integer.parseInt(arr[1]); //除数 System.out.println("两个数的商是:" + dividend / divisor); }catch(ArithmeticException ae){ System.out.println("除数不能为0"+ae.toString()); }finally{ System.out.println("捕获除数0结束"); } }catch(NumberFormatException nfe){ System.out.println("获取到的不是数字"+nfe.toString()); }finally{ System.out.println("捕获是否为数字结束"); } System.out.println("抓捕结束"); }} class Exceptions{ public static void main(String[] args) { String arr[]={"a", "b"}; Computer c=new Computer(); c.count(arr); }}
将数组内的元素都改为数字,且第二个为0时,
五. 抛出异常:
用于显示地引发异常。
1. throws,写在函数头,后面跟着异常对象。它是领导,负责喊话的。
2. throw,写在函数体内,后面跟着异常类。它是群众,真正干事的。执行此句后不再执行下面的语句。
class Computer{ //显式的提示预防可能发生的异常 void count(int i) throws ArithmeticException { System.out.println(8/i); }} class Exceptions{ public static void main(String[] args) { Computer c=new Computer(); try { c.count(0); } catch(ArithmeticException ae) { System.out.println("算数异常:"+ae.toString()); } System.out.println("异常处理结束"); }}
显式地处理多个异常,
class Computer{ //显式的提示预防可能发生的异常,多个 void count(int i) throws ArithmeticException,ArrayIndexOutOfBoundsException { System.out.println(8/i); int num[]=new int[i]; System.out.println(num[i]); }} class Exceptions{ public static void main(String[] args) { Computer c=new Computer(); try { c.count(1); } catch(ArithmeticException ae) { System.out.println("算数异常:"+ae.toString()); } catch(ArrayIndexOutOfBoundsException aiobe) { System.out.println("数组越界:"+aiobe.toString()); } System.out.println("异常处理结束"); }}
六. 自定义异常:
有些情况是Java不能捕捉到的,尤其是我们自己定义的异常情况。比如要获取一个人名,如果是本拉登,就宕机。所以我们需要自定义一个异常来处理本拉登。
自定义的异常须要继承自Java的异常类,比如Exception根类。任何与本拉登相关的调用都要让throws通知一下,否则出现一下编译错误,
看例子:
//自定义的处理本拉登的异常类class OsamabinladenException extends Exception{} class NameShow{ //这里可能遇到本拉登,需要领导通知一下 void showName(String name) throws OsamabinladenException { if(name=="Osamabinladen") { //遇到本拉登了就抛出异常处理 throw new OsamabinladenException(); }else{ System.out.println(name); } }} class Exceptions{ public static void main(String[] args) { NameShow ns=new NameShow(); try { ns.showName("Osamabinladen"); } catch(OsamabinladenException oe) { System.out.println(oe.toString()); } }}
我们可以调用Exception的构造方法返回一些信息,
——–
没有伞的孩子必须努力奔跑!