Java中的异常处理

  Java所有非正常情况分为两种:Error和Exception,都继承Throwable。

  Error一般指与虚拟机相关的问题,如系统崩溃、虚拟机错误、动态链接失败等,这种错误无法恢复或不可能捕获,将导致应用程序中断。通常应用程序无法处理这些错误,因此无需使用catch块捕获异常或使用throws抛出异常。

  异常捕获时,先捕获小异常,再捕获大异常。  

 

1、Java7提供的多异常捕获

  捕获多种类型的异常时,用“|“隔开,并且异常变量有隐式的final修饰,不能对异常变量重新赋值。

2、使用finally回收资源

  垃圾回收机制不会回收任何物理资源,只能回收堆内存中对象占用的内存。

注意:除非在try块、catch块里调用了退出虚拟机的方法,否则不管在try块、catch块里执行了怎样的代码(包括return),出现怎样的情况,异常处理的finally块一定会执行。尽量避免在finally里执行return或throw语句。

3、Java7的自动关闭资源的try块

  Java7的增强:它允许在try关键字后紧跟一对圆括号,圆括号可以声明、初始化一个或多个资源,此处的资源指的是那些必须在应用程序结束时显式关闭的资源(如数据库连接、网络连接)等,try语句会在该语句结束时自动关闭资源。

注意:这些资源必须实现AutoClosable或Closable接口,实现close()方法。Closable抛出IOException异常,AutoClosable抛出任何异常。

4、Checked异常和Runtime异常

  Java的异常分为两大类:Checked异常和Runtime异常。所有的RuntimeException类及其子类的实例被称为Runtime异常;其他的则为Checked异常。

  只有Java语言提供了Checked异常。Java语言认为Checked异常都是可以被处理或修复的异常,所以Java必须显式处理Checked异常。如果程序没有处理Checked异常,该程序在编译时就会发生错误,无法通过编译。

对于Checked异常的处理方式有两种:

  •   当前方法明确知道如何处理该异常,程序应该使用try...catch块来捕获该异常,然后在对应的catch块中修复该异常。
  •   当前方法不知道如何处理该异常,程序应该在定义该方法时声明抛出该异常。

  Runtime异常无须显式声明抛出,如果程序需要捕获Runtime异常,也可以使用try...catch块来实现。

  •     使用throws声明抛出异常

使用throws声明抛出异常的思路是,当前方法不知道如何处理这种类型的异常,该异常一个由上一级调用者处理;如果main方法也不知道如何处理这种类型的异常,也可以使用throws声明抛出异常,该异常将交给JVM处理。JVM对异常的处理方法是,打印异常的跟踪栈信息,并中止程序运行。

注意:throws只能在方法签名中使用,可以抛出多个异常,以逗号分隔。

  如果某段代码中调用了一个带throws声明的方法,该方法声明抛出了Checked异常,则表明该方法希望它的调用则来处理该异常。也就是说,调用该方法时要么放在try块中显式捕获该异常,要么放在另一个带throws声明抛出的方法中。

public class CheckExceptionTest {
    public static void main(String[] args) throws FileNotFoundException {
        // 因为test()方法声明抛出FileNotFoundException异常,所以调用该方法的代码要么放在try...catch块中,要么处于另一个带throws声明抛出的方法里。
        testCheckedException();
    }

    private static void testCheckedException() throws FileNotFoundException {
        // 因为FileInputStream的构造器声明抛出FileNotFoundException异常,所以调用FileInputStream的方法要么放在try...catch块中,要么处于另一个带throws声明抛出的方法里。
        FileInputStream fis = new FileInputStream("a.txt");
    }
}

  使用throws声明抛出异常时有一个限制,就是方法重写时的“两小”中的一条规则:子类方法声明抛出的异常类型应该是父类方法声明抛出的异常类型的子类或相同。

5、使用throw抛出异常

  当程序出现错误时,系统会自动抛出异常;除此之外,Java也允许程序自行抛出异常,自行抛出的异常使用throw语句来完成。

6、catch和throw同时使用

  • 在出现异常的方法内捕获并处理异常,该方法的调用者将不能再次捕获该异常。
  • 在方法签名中声明抛出该异常,将该异常完全交给方法调用者处理。

 catch和throw结合使用,既可以在应用后台通过日志来记录异常发生的详细情况,也可以向应用使用者传达某种提示。

7、异常链

  程序先捕获原始异常,然后抛出一个新的业务异常(包含了对用户的提示信息),这种处理方式被称为异常转译。

try
{
// 业务逻辑
...
}
catch(Exception e)
{
// 记录原始异常
...
// 向上抛出异常
throw new IOException(e);
}

  这种把捕获一个异常然后接着抛出另一个异常,并把原始异常信息保存下来是一种典型的链式处理(23中设计模式之一:职责链模式),也被称为“异常链”。

 8、Java的异常跟踪栈

java.io.FileNotFoundException: a.txt (系统找不到指定的文件。)
	at java.io.FileInputStream.open0(Native Method)
	at java.io.FileInputStream.open(FileInputStream.java:195)
	at java.io.FileInputStream.<init>(FileInputStream.java:138)
	at java.io.FileInputStream.<init>(FileInputStream.java:93)
	at com.springTest.exception.CheckExceptionTest.testCheckedException(CheckExceptionTest.java:30)
	at com.springTest.exception.CheckExceptionTest.main(CheckExceptionTest.java:16)

 9、异常处理规则

  • 不要过度使用异常
  • 不要使用过于庞大的try块
  • 避免使用catch all 语句,即catch(Throwable t)
  • 不要忽略捕获到的异常,采取的措施如:处理异常、重新抛出异常、在合适的层处理异常。

 

posted @ 2018-01-09 14:05  esther-qing  阅读(163)  评论(0)    收藏  举报