Java的异常处理主要依赖try,catch,finally,throw,和throws五个关键字,finally块用于回收在try块里打开的物理资源,异常机制保证finally块总被执行。throws关键字主要在方法签名中使用,用于声明该方法可能抛出的异常(不确定的);throw用于抛出一个实际的异常,throw可以单独作为语句使用,抛出一个具体的一场对象。
<span style="font-size:14px;">try{
//业务实现代码
...
}
catch(Exception e)
{
alert 输入不合法
goto retry
}</span>
如果执行try块里的业务逻辑代码时出现异常,系统自动生成一个异常对象,该异常对象被提交给Java运行时环境,这个过程被称为抛出(throw)异常。当java运行时环境收到异常对象时,会寻找能处理该一场对象的catch块,如果找到合适的catch块,则把该异常对象交给该catch块处理,这个过程被称为捕获(catch)异常,如果java运行时环境找不到捕获异常的catch块,则运行时环境终止,java程序也将退出。
当Java运行时环境接收到异常对象时,如何为该异常对象寻找catch块呢?catch关键字的形式:(Exception e )这意味着每个catch块都是专门用于处理该异常类及其子类的异常实例。当java运行时环境接收到异常对象后,会依次判断该异常对象是否是catch块后异常类或其子类的实例,如果是,Java运行时环境将调用该catch块来处理该异常;否则再次拿该异常对象和下一个catch块里的异常类进行比较。
注意:try块与if语句不一样,其后的{...}不可省略,即使只有一行代码,catch块与之相同。try块里声明的变量时代码块内部的局部变量,它只在try块内有效,在catch块中不能访问该变量。进行异常捕获时要把Exception类对应的catch块放在最后,而且所有的父类异常的catch块都应该排在子类异常catch块的后面(简称:先处理小异常,再处理大异常),否则编译错误。
catch块捕获多种异常:
<span style="font-family:Microsoft YaHei;font-size:14px;">public class DivTest {
try
{
int a = Integer.parseInt(args[0]);
int b = Integer.parseInt(args[1]);
int c = a/b;
System.out.println("您输入的两个数相除的结果是:"+ c);
}
catch(IndexOutOfBoundsException|NumberFormatException|ArithmeticException ie)
{
System.out.println("程序发生了数组越界、数字格式异常、算数异常之一");
//捕获多异常时,异常变量默认有final修饰
//所以下面代码有误
ie = new ArithmeticException("test");
}
catch(Exception e)
{
System.out.println("未知异常");
//捕获一种类型的异常时,异常变量没有final修饰
//下面代码正确
e = new RuntimeException("test");
}
}</span>
- 捕获多种类型的异常时,多种异常类型之间用竖线(|)隔开
- 捕获多种类型的异常时,异常变量有隐式的final修饰,因此程序不能对异常变量重新赋值。
<span style="font-family:Microsoft YaHei;font-size:14px;">public class AutoCloseTest {
public static void main(String[] args)
throws IOException
{
try(
//声明、初始化两个可关闭的资源
//try语句会自动关闭着两个资源)
BufferedReader br = new BufferedReader(new FileReader("AutoCloseTest.java"));
PrintStream ps = new PrintStream(new FileOutputStream("a.txt")))
{
//使用两个资源
System.out.println(br.readLine());
ps.println("庄生晓梦迷蝴蝶");
}
}
}</span>
Java7几乎把所有的“资源类”(包括文件IO的各种类、JDBC编程的Connection、Statement等接口……)进行了改写,最后资源实现类都实现了AutoCloseable或Closeable接口。
<span style="font-family:Microsoft YaHei;font-size:14px;">public class ThrowsTest {
public static void main(String[] args)
throws IOException
{
FileInputStream fis = new FileInputStream("a.txt");
}
}</span>
上面程序声明不处理IOException异常,将该异常交给JVM处理,程序一旦遇到该异常,JVM就会打印该异常的跟踪栈信息,并结束服务。
- 在出现异常的方法内捕获并处理异常,该方法的调用者将不能再次捕获该异常。
- 在方法签名中声明抛出该异常,将该异常完全交给方法调用者处理。
<span style="font-family:Microsoft YaHei;font-size:14px;">public class AuctionTest {
private double initPrice = 30.0;
//因为该方法中显示抛出了AuctionException异常
//所以在此处需要显示声明抛出AuctionException异常
public void bid(String bidPrice)
throws AuctionException
{
double d = 0.0;
try
{
d = Double.parseDouble(bidPrice);
}
catch(Exception e)
{
//此处完成本方法中可以对异常执行的修复处理
//此处仅仅是在控制台打印异常的跟踪栈信息
e.printStackTrace();
//再次抛出自定义异常
throw new AuctionException("竞拍价必须是数值," + "不能包含其他字符");
}
if(initPrice > d)
{
throw new AutionException("竞拍价比起拍价低" + "不允许竞拍");
initPrice = d;
}
public static void main(String[] args)
{
AuctionTest at = new AuctionTest();
try
{
at.bid("df");
}
catch(AuctionException ae)
{
//再次捕获到bid()方法中的异常,并对该异常进行处理
System.err.println(ae.getMessage());
}
}
}
}
</span>