java异常处理

简介:

java中的异常处理的目的在于通过使用少量的代码,使得程序有着强大的鲁棒性。可以使程序中的异常处理代码和正常业务代码分离。

java的异常机制主要依赖于五个关键字:try、catch、 finally、 throw、 throws、

try:后紧跟一个花括号扩起来的代码块,,放置可能引发异常的代码

catch:用于处理这种类型的代码,

finally:回收try中打开的物理资源,一定会执行

throws:在方法签名中使用,声明该方法可能抛出的异常

throw:抛出一个实际的异常

1、异常处理机制

1.1、使用try...catch捕获异常

try {
            //业务实现代码
        }
        catch (Exception e){
            //异常处理代码
        }

  如果在执行try块里的业务逻辑代码时出现了异常,系统会自动生成一个异常对象,该异常对象被提交给java运行时环境,此过程被称为抛出异常

  异常对象交给catch块处理,这个过程称为:捕获异常

  注意:如果出现异常的代码块没有被try...catch包含,则也会生成一个异常对象,但是无法找到处理该异常的catch块,程序就会异常退出

1.2、异常类的继承体系

  try块后可以跟多个catch块。

  运行代码过程中,发生不同的意外,抛出的异常对象不同。java收到异常对象后,会依次判断该异常对象是否是catch块后异常类或者其子类的事例,找到合适的catch执行

  执行过程如下图所示:

代码事例如下:

try{
            int a=Integer.parseInt(args[0]);
            int b=Integer.parseInt(args[1]);
            int c=a/b;
            System.out.println("c的结果为:"+c);
        }
        catch (IndexOutOfBoundsException ie){
            System.out.println("数组出界");
        }
        catch(NumberFormatException ne){
            System.out.println("数字格式不正确");
        }
        catch(ArithmeticException ae){
            System.out.println("算数异常,分母为0");
        }
        catch (Exception e){
            System.out.println("其他错误");
        }

  

java提供多个异常类,之间都有继承关系,如下图所示:

1.3、多捕获异常:使用一个catch块捕获多个异常,多种类型异常之间用“|”隔开,且异常变量默认为final类型,不能被改变。例如:

try{
            int a=Integer.parseInt(args[0]);
            int b=Integer.parseInt(args[1]);
            int c=a/b;
            System.out.println("c的结果为:"+c);
        }
        catch(IndexOutOfBoundsException|NumberFormatException|ArithmeticException ie){
            System.out.println("异常");
       //ie=new ArithmeticException("test"); 此行会不通过编译,因为ie对象为final类型,不能被修改
        }

1.4、访问异常信息

getMessage();返回该异常的详细信息
printStackTrace();将该异常的跟踪栈信息输出到标准错误输出
printStackTrace(PrintStream s);将改异常的跟踪栈信息输出到指定输出流
getStackTrace();返回该异常的跟踪栈信息

1.5、使用finally回收资源

回收try块打开的物理资源(数据库连接,网络连接,磁盘文件等等),catch块和finally块至少出现一个,finally如果有必须放在catch之后

 FileInputStream fis=null;
        try{
            fis=new FileInputStream("a.txt");

        } catch (FileNotFoundException e) {
            e.printStackTrace();
            return;
            //system.exit(1);
        }finally {
            //关闭磁盘文件
            if(fis!=null){
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("已关闭资源");
        }

注意:catch中执行了return后还会执行finally代码块

但是catch中执行了system.exit(1);后就会退出虚拟机

1.6、自动关闭资源的try语句,try中加入参数,java7后代码下:

try(BufferedReader br=new BufferedReader(new FileReader("a.txt"))){
            System.out.println("try自动关闭资源");
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

java9改进之后代码:

FileReader f=new FileReader("a.txt");
        BufferedReader br=new BufferedReader(f);
        try (br){
            System.out.println("自动关闭资源");
        }

 1.7、使用throws声明抛出异常

思路:当前方法不知道该如何处理此类异常时,由上一级调用者处理此异常,main函数也可以使用throws,向上交给JVM处理

public static void main(String[] args) throws IOException {
        FileReader f = new FileReader("a.txt");
    }

1.8、catch和throw同时使用

总结以上介绍的异常处理方式有两种分别为:

(1)在出现异常的方法内捕获并处理异常,改方法的调用者将不能再次捕获该异常

(2)该方法签名中声明抛出异常,将该异常完全交给方法调用者去处理

实际应用中往往有复杂情况,需要几个方法同时协作才能处理该异常,也就是说,当出现异常时,该方法只能对部分异常进行处理,部分异常需要调用者去处理,例如:

public class AuctionTest {
    private double initPrice=30.0;
    public void bid(String price) throws ArithmeticException{
        double d=1.0;
        try{
            d=Double.parseDouble(price);
        }catch (Exception e){
            e.printStackTrace();
            throw new ArithmeticException();
        }
    }

    public static void main(String[] args) {
        AuctionTest at=new AuctionTest();
        try {
            at.bid("wangli");
        }catch (ArithmeticException e){
            System.out.println("捕获到bid抛出的异常,进行处理");
        }
    }
}

bid方法中catch块对异常进行处理时也抛出了异常,,会通知该方法的调用者再次处理抛出的异常。

1.9、java7增强的throw语句

在java7以前检测到e为什么异常类型就会抛出什么异常,简单粗暴,java7之后会检测e的实际类型

public class ThrowTest2 {
    public static void main(String[] args) throws FileNotFoundException {
        try {
            FileOutputStream fileOutputStream = new FileOutputStream("1.txt");
        } catch (Exception e) {
            //java7在检查throw e时可能抛出异常的实际类型
            //因此在此处声明抛出FileNotFoundException异常即可
            e.printStackTrace();
            throw e;
        }

    }
}

1.10、异常链

在实际应用中,常常会有分层关系,层与层之间有非常清晰的划分,上一层功能的实现又依赖于下层的API,本层得到下层的异常后不能反馈给上一层,这样会暴露信息。通常做法为:

程序先捕获原始异常,然后抛出一个新的业务异常,叫做异常转译

 public void calSal() throws SalException{
        try {
            //业务逻辑
        }catch (SQLException se){
            //原始异常进行记录
            //抛出新的异常
            throw new salException("系统出现错误");
        }
    }

1.11、自定义异常类

用户自定义异常都应该继承Exception基类,自定义异常类需要提供两个构造器,一个无参,一个带一个字符串参数的构造器

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

 

 



 

 

原文地址:https://www.cnblogs.com/lili-work/p/9376528.html