从0开始复习Java(7)--Exception

2017-04-26  本文已影响22人  ifeelok0319

Java将异常分为两类:Checked异常和Runtime异常。Java认为前者都是可以在编译阶段被处理的异常,所以它强制程序处理所有的Checked异常;而Runtime异常则无需处理。

一、异常概述

try{
    //业务实现代码
}
catch (Exception e){
}
finally {
}

try块里面的业务逻辑代码出现异常,则系统自动生成一个异常对象,该异常对象被提交给Java运行时环境,这个过程成为抛出(throw)异常。Java运行时环境去寻找处理该异常对象的catch块,找到合适的则把该异常对象交给该块处理,成为捕获(catch)异常;找不到则运行时环境终止。

try块后面的花括号不能省略,它定义的变量在catch块中不能访问。catch也不能省略花括号。

Java异常类继承关系Java异常类继承关系

二、异常处理机制

多异常捕获

Java7开始,一个catch可以捕获多种类型的异常。需要注意:

public class Test{
    public static void main(String[] args) {
        try{
            int a = Integer.parseInt(args[0]);
            int b = Integer.parseInt(args[1]);
            int c = a/b;
        }
        catch (IndexOutOfBoundsException|NumberFormatException|ArithmeticException e){
            //下面报错
            e = new ArithmeticException("test");
        }
        catch (Exception e){
            e = new RuntimeException("test");
        }
    }
}

访问异常信息

使用finally回收资源

Java回收机制不会回收物理资源,只能回收对内存中对象所占用的内存。

即使是try或者catch语句里面有return语句,finally块也会执行。

异常处理语法结构中只有try块是必须的,catchfinally块至少出现一个,也可以同时出现。

import java.io.FileInputStream;
import java.io.IOException;

public class Test{
    public static void main(String[] args) {
        FileInputStream fis = null;
        try{
            fis = new FileInputStream("a.txt");
        }
        catch(IOException e){
            System.out.println(e.getMessage());
            //下面方法继续执行finally
            //return;
            //下面方法退出虚拟机,不会执行finally
            //System.exit(1);
        }
        finally{
            if(fis!=null){
                try{
                    fis.close();
                }
                catch(IOException e){
                    System.out.println(e.getMessage());
                }
            }
        }
    }
}

一旦在finally块中使用throwreturn语句,trycatch语句中的相应语句将会失效。

自动关闭资源的try语句

Java7开始,允许将那些必须在程序结束时显式关闭的资源放在try后面的圆括号里面。

这些资源实现类必须实现AutoCloseableCloseable接口,这两个接口有close方法。

import java.io.BufferedReader;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.PrintStream;

public class Test{
    public static void main(String[] args) {
        try(
            BufferedReader br = new BufferedReader(new FileReader("test.txt"));
            PrintStream ps = new PrintStream(new FileOutputStream("a.txt"));
        ){
            ps.println("this is nothing");
        }
    }
}

Java7几乎把所有的资源类进行了改写,都实现了AutoCloseableCloseable接口

三、Checked异常和Runtime异常

所有RuntimeException类及其子类的实例被称为Runtime异常,其他的被称为Checked异常。

Checked异常体现了Java的设计哲学--没有完善错误处理的代码根本就不会被执行。该类异常的处理方式:

使用throws声明抛出异常

如果main方法也不知道怎么处理异常,则交给jvm处理。jvm打印异常的跟踪栈信息,并终止程序运行。

throws ExceptionClass1, ExceptionClass2...

子类方法声明抛出的异常应该是父类方法声明抛出的异常类型的子类或相同,子类方法声明的异常不允许比父类方法声明抛出的异常多。

在大部分时候推荐使用Runtime异常

四、使用throw抛出异常

throw语句抛出的不是异常类,而是异常实例,而且每次只能抛出一个异常实例。

throw ExceptionInstance;

规则:

  1. throw语句抛出的是Checked异常,该throw语句要么处于try块里,显式捕获该异常,要么放在一个带throws声明抛出的方法中,把该异常交给该方法的调用者处理
  2. throw语句抛出的是Runtime异常,则该语句无需放在try块里,也无需放在throws方法中;
  3. 程序既可以显式使用try...catch捕获并处理该异常,也可以完全不理会,把该异常交给该方法的调用者。

自定义异常类

用户自定义异常应该继承Exception类。

通常需要实现两个构造器,如下:

public class AuctionException extends Exception{
    public AuctionException(){}
    public AuctionException(String msg){
        super(msg);
    }
}

catch和throw同时使用

在实际应用中往往需要更复杂的处理方式:
当一个异常出现时,必须由几个方法协作才能完全处理该异常。

异常链

自定义异常类需要多实现一个方法。

public class TestException extends Exception{
    public TestException(){}
    public TestException(String msg){
        super(msg);
    }
    public TestException(Throwable t){
        super(t);
    }
}

五、Java的异常跟踪栈

六、异常处理规则

不要过度使用异常

对于普通的错误,应该编写处理错误的代码,对于外部的、不能确定和预知的运行时错误才使用异常。

避免过大的try语句

避免使用catchAll语句

不要忽略捕获到的异常

上一篇 下一篇

猜你喜欢

热点阅读