java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > Java异常处理特性

Java学习之异常处理的新特性详解

作者:一一哥Sun

异常处理机制是Java很早时就搞出来的技术,但在实际应用中,我们发现这个异常处理也有一些不完善的地方,接下来主要给大家介绍一下Java异常处理的一些新特性,需要的朋友可以参考下

一. 异常处理新特性

异常处理机制是Java很早时就搞出来的技术,但在实际应用中,我们发现这个异常处理也有一些不完善的地方。比如在操作IO流时经常需要关闭IO资源,这些代码就得放在finally代码块中,而在finally中关闭IO流时,又会提示我们需要再次捕获异常。或者有时我们在一个方法中,同时要捕获多个异常,这就需要使用多个catch代码块。但这样一来,我们写出来的代码就显得特别啰嗦繁琐,所以很多Java程序员就很希望能够简化这种操作。而Java团队也很重视大家的反馈,在新的JDK版本中对此进行了相关的优化,接下来就给大家说一下关于异常处理的新特性。

1. 多异常捕获

1.1 存在的问题

我们先来回顾一下在使用try-catch多重结构时存在的问题,比如下面这样的代码:

try{
    // 可能会发生异常的语句
} catch (FileNotFoundException e) {
    // 调用方法methodA处理
} catch (IOException e) {
    // 调用方法methodA处理
} catch (ParseException e) {
    // 调用方法methodA处理
} catch(...){
   ....
}

相信大家对上面这样的代码块已经不陌生了,这种多catch的代码块虽然客观上提高了程序的健壮性,但也让我们的代码量大大的增加,可读性降低了很多。其实代码中虽然有些异常的种类不同,但如果捕获之后的处理是相同的,那是否可以把多个异常合并在一起处理呢?

1.2 解决办法

为了解决多catch代码块的问题,在JDK 7中,Java开始支持”多异常捕获“技术,允许我们把多个异常进行合并处理。我们来看看如下案例:

public static void main(String[] args) {
    try {
        int a = Integer.parseInt("100");
        int b = a / 0;
        System.out.println("b=" + b);
    } catch (IndexOutOfBoundsException | NumberFormatException | ArithmeticException e) {
        System.out.println("异常信息="+e.getMessage());
        e.printStackTrace();
        // 捕获多个异常时,异常对象e的前面默认有final修饰,e对象不能被重新赋值
        // 否则会产生如下异常:The parameter e of a multi-catch block cannot be assigned
        //e = new ArithmeticException("test");
    } catch (Exception e) {
        System.out.println("e,异常信息="+e.getMessage());
        e.printStackTrace();
        // 捕获一种类型的异常时,异常变量没有final修饰,e变量可以被重新赋值
        e = new RuntimeException("test");
    }
}

在上面的代码中,我们在一个catch()中同时捕获了”IndexOutOfBoundsException | NumberFormatException | ArithmeticException“多个异常对象。但是我们要注意,在捕获多个异常对象时,异常对象e的前面默认会带有final修饰,所以e对象就不能再被重新赋值,否则会产生如下异常:The parameter e of a multi-catch block cannot be assigned。而默认的单个异常对象捕获时,并不会带有final修饰符。

1.3 小结

根据上面的案例,再把本节内容给大家总结一下:

  • 捕获多种类型异常时,多种异常类型之间要用竖线 | 隔开;
  • 捕获多种类型异常时,异常变量前默认带有隐式的final修饰,我们不能再对异常变量重新赋值。

2. 自动资源管理

2.1 概述

在Java中,我们经常需要管理一些资源,例如文件、数据库连接、网络连接等。在使用完这些资源后,我们需要关闭它们以释放系统资源,否则可能会导致系统崩溃或资源泄漏。在以前的代码实现中,经常需要在finally代码块中对这些资源进行关闭,最终写出来的代码就特别啰嗦。

后来JDK 7给我们增加了一个新特性,该特性可以自动关闭资源文件,被称为自动资源管理(Automatic Resource Management,简称ARM) 。这样,我们在处理异常时,就可以利用自动资源管理来正确地管理这些资源,避免因为忘记关闭资源而导致一些问题。

2.2 自动资源管理

所谓的自动资源管理,是指我们在使用IO流等物理资源时,程序会自动为我们释放这些资源,无需再手动调用关闭资源的方法。自动资源管理主要是通过try-with-resources语句进行实现,该语句是从JDK 7版本中开始引入的。但如果我们想使用该功能,需要满足以下两个条件:

物理资源对象必须实现AutoCloseable接口或其子接口Closeable,Closeable接口只有一个close()方法,用于关闭资源。

try-with-resources的代码块只能使用try语句中声明的资源对象。

AutoCloseable接口是在Java 7中新增的接口,用于指示资源需要在使用完毕后关闭。Java 7几乎把所有的“资源类”(包括各种文件IO类、JDBC的Connection 和 Statement等接口)都进行了改写,改写后的资源类都实现了AutoCloseable 或 Closeable接口。这样当try-with-resources语句执行完成后,Java就会自动调用资源对象的close()方法释放资源。即使try语句块中发生了异常,也会自动关闭资源,确保了资源在使用完后被正确的关闭。

2.3 代码案例

接下来再通过一个代码案例来演示自动资源管理该如何实现。

public class Demo10 {
    public static void main(String[] args) {
        //try中声明的资源对象默认会带有final修饰符,try中可以同时声明多个资源对象
        try(BufferedReader br = new BufferedReader(new FileReader("file.txt"))) {
            String line;
            while ((line = br.readLine()) != null) {
                System.out.println(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }//这里就没有使用finally代码,Java会自动关闭IO流
    }
}

在上面的例子中,我们就使用了try-with-resources语句来读取一个文件,try语句中声明的资源会被隐式声明为final,且在一条try语句中可以同时声明或初始化多个资源。BufferedReader和FileReader都实现了AutoCloseable接口,因此在使用完之后,它们会被自动关闭。

而且你会发现,其实try-with-resources的用法和try-catch是一样的,但不用我们再编写finally代码了。这是因为自动关闭资源中的try语句,相当于包含了隐式的finally块,这个finally块会自动关闭资源。所以这样我们就可以简化代码,避免代码中出现大量的 try-catch块和finally块,使代码更加简洁易读,而且能够自动处理多个资源的关闭,避免了繁琐的手动关闭操作。

2.4 增强的自动资源管理

虽然JDK 7中的自动资源管理已经让我们的代码很简化了,但很多人觉得还是不够,所以在JDK 9中又再次增强了自动资源管理功能。JDK 9允许我们将多个资源变量放在try语句后的圆括号中,但不要求我们在try语句的圆括号中声明并创建资源,只需要把自动关闭的资源带有final修饰即可。 接下来再通过一个案例给大家演示一下JDK 9的特性。

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
/**
 * @author 一一哥Sun 
 */
public class Demo11 {
    public static void main(String[] args) throws IOException {
        //需要在资源对象前面添加final修饰符
        //读取一个文件
        final FileReader fileReader = new FileReader("file.txt");
        final BufferedReader br = new BufferedReader(fileReader);
        //JDK 9之后,try()后的括号中可以同时捕获处理多个资源对象,会对这多个资源对象自动关闭
        try (fileReader;br){
            String line;
            while ((line = br.readLine()) != null) {
                System.out.println(line);
            }
        } 
    }
}

在上面的案例中,我们需要在资源对象前面添加final修饰符,并且try()后的括号中可以同时捕获处理多个资源对象,多个对象之间用分号";"进行分割,最终Java会对这多个资源对象自动关闭。

2.5 注意事项

我们在使用try-with-resources时需要注意以下几点:

  • try-with-resources语句块中的资源必须实现 AutoCloseable 或Closeable接口,否则编译器会报错;
  • 在try-with-resources语句块中,当异常抛出时,会按照资源的创建顺序依次关闭每个资源;
  • 如果在关闭某个资源时抛出了异常,该异常会被抑制(suppressed),并添加到try块中抛出的异常中,我们可以通过getSuppressed方法获取抑制的异常;
  • 除了Java标准库中自带的资源对象,我们也可以自定义资源对象,自定义资源对象时需要实现AutoCloseable接口或其子接口Closeable。

二. 结语

至此,就把异常的新特性也给大家讲解完毕了.

以上就是Java学习之异常处理的新特性详解的详细内容,更多关于Java异常处理特性的资料请关注脚本之家其它相关文章!

您可能感兴趣的文章:
阅读全文