当运行时发生的错误就是异常,而不是编译时发生的语法错误。比如下面:
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的构造方法返回一些信息,
--------