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

 更新时间:2023年08月22日 09:22:52   作者:一一哥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异常处理特性的资料请关注脚本之家其它相关文章!

相关文章

  • 一文带你你搞懂Java的3种IO模型

    一文带你你搞懂Java的3种IO模型

    在Java中,一共有三种IO模型,分别是阻塞IO(BIO)、非阻塞IO(NIO)和异步IO(AIO),本文将给大家详解的介绍这三种IO模型,文中有相关的代码示例,需要的朋友可以参考下
    2023-05-05
  • 运用Spring Aop+注解实现日志记录

    运用Spring Aop+注解实现日志记录

    我们都知道Spring框架的两大特性分别是 IOC (控制反转)和 AOP (面向切面),这个是每一个Spring学习视频里面一开始都会提到的,这里,如果我们使用Aop来记录日志,那是再好不过了,感兴趣的朋友跟随小编一起学习下Spring Aop注解实现日志记录的过程吧
    2022-01-01
  • 使用JAVA实现高并发无锁数据库操作步骤分享

    使用JAVA实现高并发无锁数据库操作步骤分享

    一个在线2k的游戏,每秒钟并发都吓死人。传统的hibernate直接插库基本上是不可行的。我就一步步推导出一个无锁的数据库操作,详情看下文
    2013-11-11
  • 一学即会之JDK版本快速切换方法(2024)

    一学即会之JDK版本快速切换方法(2024)

    这篇文章主要介绍了一学即会之JDK版本快速切换方法,详细给大家讲解了如何下载、安装和配置多个JDK版本,并通过设置环境变量和编写批处理脚本来切换JDK版本,需要的朋友可以参考下
    2025-03-03
  • maven pom中内置变量及引用的实现

    maven pom中内置变量及引用的实现

    maven其实有很多内置变量供开发着在开发中使用,本文主要介绍了maven pom中内置变量及引用的实现,具有一定的参考价值,感兴趣的可以了解一下
    2024-01-01
  • java网上图书商城(4)购物车模块1

    java网上图书商城(4)购物车模块1

    这篇文章主要为大家详细介绍了java网上图书商城,购物车模块,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-12-12
  • mybatis新增save结束后自动返回主键id详解

    mybatis新增save结束后自动返回主键id详解

    这篇文章主要介绍了mybatis新增save结束后自动返回主键id详解,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-12-12
  • SpringBoot框架实现支付和转账功能

    SpringBoot框架实现支付和转账功能

    在 Spring Boot 框架中实现支付和转账功能时,涉及到多个细节和注意点,这些功能通常需要高度的安全性、稳定性和可扩展性,本文介绍了实现支付和转账功能的一些关键点,需要的朋友可以参考下
    2024-08-08
  • Java 内部类的定义与范例

    Java 内部类的定义与范例

    说起内部类这个词,想必很多人都不陌生,但是又会觉得不熟悉。原因是平时编写代码时可能用到的场景不多,用得最多的是在有事件监听的情况下,并且即使用到也很少去总结内部类的用法。今天我们就来一探究竟
    2021-11-11
  • Springboot+AOP实现时间参数格式转换

    Springboot+AOP实现时间参数格式转换

    前端传过来的时间参数,后端可以自定义时间格式转化使用,这样想转成什么就转成什么。本文将利用自定义注解AOP实现时间参数格式转换,感兴趣的可以了解一下
    2022-04-04

最新评论