|
|
本帖最后由 pansong291 于 2019-4-2 13:25 编辑
上篇:47.异常(一)---面向对象
下篇:49.异常(三)---面向对象
注意:如果你的回复只是“感谢分享”、“辛苦了”之类的与教程内容无关的字眼,还请不要回复本帖,谢谢合作!!!
注意:如果你的回复只是“感谢分享”、“辛苦了”之类的与教程内容无关的字眼,还请不要回复本帖,谢谢合作!!!
注意:如果你的回复只是“感谢分享”、“辛苦了”之类的与教程内容无关的字眼,还请不要回复本帖,谢谢合作!!!
自定义异常与 Throw 关键字
我们通过查阅 JDK 文档资料,就能看到,Exception 类是 java.lang.Throwable 类的子
类,Exception 类继承了 Throwable 类的所有方法。其实,我们在实际应用中,是使用
Exception 的子类来描述任何特定的异常的。Exception 类是所有异常类的父类,Java 语言
为我们提供了许多 Exception 类子类,分别对应不同的异常类型,如我们在前面已经看到过
以下几个异常。
● ArithmeticException(在算术运算中发生的异常,如除以零)
● NullPointerException(变量还没有指向一个对象,就引用这个对象的成员)
● ArrayIndexOutOfBoundsException(访问数组对象中不存在的元素)
除了系统提供的异常,我们也可以定义自己的异常类,自定义的异常类必须继承
Exception 类。假设我们在上面程序的 devide 函数中,不允许有负的被除数,当 devide 函
数接收到一个负的被除数时,程序返回一个自定义的异常(这里就叫负数异常吧!)通知调
用者。我们可以这样定义这个负数异常类。
class DevideByMinusException extends Exception
{
int devisor;
public DevideByMinusException(String msg,int devisor)
{
super(msg);
this.devisor = devisor;
}
public int getDevisor()
{
return devisor;
}
}
Java 是通过 throw 关键字抛出异常对象的,其语法格式是
throw 异常对象;
如果我们的程序想跳转,我们可以抓住自己抛出的异常。否则,则此方法应声明抛出异
常,而由该方法的调用者负责处理。
如果我们要在 devide 函数接收到的第二个参数(也就是被除数)为负数时,向调用者
抛出自定义的 DevideByMinusException 对象,程序代码如下:
class Test
{
public int devide(int x, int y) throws ArithmeticException, DevideByMinusException
{
if(y < 0)
throw new DevideByMinusException("被除数为负", y);
//这里抛出的异常对象,就是调用者在 catch(Exception e){}语句中接收的变量 e。
int result = x/y;
return x/y;
}
}
我们能够看到,上面的代码中,devide 方法声明时抛出了两个异常。java 中一个方法
是可以被声明成抛出多个异常的。
下面再来看看调用程序应该如何对 devide 方法中的多个异常作出处理。
public class TestException
{
public static void main(String [] args)
{
try
{
int result = new Test().devide( 3, 0 );
//int result = new Test().devide( 3, -1 );
//int result = new Test().devide( 3, 1 );
System.out.println("the result is " + result );
}
catch(DevideByMinusException e)
{
System.out.println("program is running into DevideByMinusException");
System.out.println(e.getMessage());
System.out.println("the devisor is " + e. getDevisor());
}
catch(ArithmeticException e)
{
System.out.println("program is running into ArithmeticException");
System.out.println(e.getMessage());
}
catch(Exception e)
{
System.out.println("program is running into other unknowned Exception");
System.out.println(e.getMessage());
}
System.out.println("program is running here ,that is normal !");
}
}
上面的程序使用一个 try 后面跟着多个 catch 来捕捉异常,每一个 catch 可以处理一个
不同的异常类型。如果我们调用 devide(3,0),将发生 ArithmeticException 异常,程序将跳
转至 catch(ArithMeticException e)代码块中执行。如果我们调用 devide(3,-1),将发生
DevideByMinusException 异常,程序将跳转至 catch(DevideByMinusException e)代码块中
执行。如果在 devide 方法中发生了 ArithmeticException、DevideByMinusException 之外的
任何其他异常,程序将跳转至 catch(Exception e)代码块中执行,也就是还没有由前面的
catch 处理的异常,都将由 catch(Exception e)代码块处理,不是因为该语句是最后一个
catch,而是由于 Exception 是所有异常类的父类,从语法上来讲,是能够处理所有异常的。
所以,各种 catch 代码块的放置顺序非常重要,catch(Exception e)不能放在其他 catch 语
句的前面,否则后面的 catch 永远得不到执行,就没有什么意义了。大家可以用 if,else if,
else if,else 结构去考虑 try...catch 问题。读者可以逐一去掉程序中被注释的 devide
语句的注释符,注释掉其他的 devide 语句,对比观察运行结果。
多学两招:
我们可以在一个方法中使用 throw,try…catch 语句来实现程序的跳转,下面是描述这
种方法的一段简要程序代码:
void fun()
{
try
{
if(x==0)
throw new YyyException("Yyy"); //跳转到代码块 1 处
else if(x==1)
throw new XxxException("Xxx"); //跳转到代码块 2 处
}
catch(YyyException e)
{
代码块1
}
catch(XxxException e)
{
代码块2
}
}
finally 关键字
在 try…catch 语句后,我们还可以有个 finally 语句,finally 语句中的代码块不管异
常是否被捕获总是要被执行的。我们将上面的程序作如下修改,来看看 finally 语句的用法
与作用。
public class TestException
{
public static void main(String [] args)
{
try
{
int reslut = new Test().devide( 3, 0 );
//int reslut = new Test().devide( 3, -1 );
//int reslut = new Test().devide( 3, 1 );
System.out.println("the result is" + result );
//return ;
}
catch(DevideByMinusException e)
{
System.out.println("program is running into DevideByMinusException");
System.out.println(e.getMessage());
System.out.println("the devisor is " + e. getDevisor());
System.exit(0);
}
catch(ArithMeticException e)
{
System.out.println("program is running into ArithMeticException");
System.out.println(e.getMessage());
return ;
}
catch(Exception e)
{
System.out.println("program is running into other unknowned Exception");
System.out.println(e.getMessage();
}
finally
{
System.out.println("program is running into finally");
}
System.out.println("program is running here ,that is normal !");
}
}
爱思考的读者也许会问:程序中的最后一句 System.out.println("program is running here ,that is normal !");
不论有没有异常发生,该语句都会执行,那何必还用 finally 语句呢?
finally 还是有其特殊之处的,即使 try 代码块和 catch 代码块中使用了 return 语句
退出当前方法或 break 跳出某个循环,相关的 finally 代码块都要执行,读者可以逐一去掉
程序中被注释的 devide 语句的注释符,注释掉其他的 devide 语句,对比观察运行结果。
finally 中的代码块不能被执行的唯一情况是:在被保护代码块中执行了System.exit(0)。
每个 try 语句必须有一个或多个 catch 语句对应,try 代码块与 catch 代码块及 finally
代码块之间不能有其他语句。如下面的代码是非法的。
try
{
……
}
x = 3 + 5; //代码位置是非法的
catch(Exception e)
{
……
}
上篇:47.异常(一)---面向对象
下篇:49.异常(三)---面向对象 |
|