文档章节

java7的异常处理新特性

柳哥
 柳哥
发布于 2014/10/06 15:02
字数 1328
阅读 739
收藏 4
点赞 0
评论 0

addSuppressed()方法

开发人员对异常处理的try-catch-finally语句块都比较熟悉。如果在try语句块中抛出了异常,在控制权转移到调用栈上一层代码之前,finally语句块中的语句也会执行。但是finally语句块在执行的过程中,也可能会抛出异常。如果finally语句块也抛出了异常,那么这个异常会往上传递,而之前try语句块中的那个异常就丢失了。如例:

package test;

public class DisappearedException {
    public void show() throws BaseException {
        try {
            Integer.parseInt("Hello");
        } catch (NumberFormatException e1) {
            throw new BaseException(e1);
        } finally {
            try {
                int result = 2 / 0;
            } catch (ArithmeticException e2) {
                throw new BaseException(e2);
            }
        }
    }
    public static void main(String[] args) throws Exception {
        DisappearedException d = new DisappearedException();
        d.show();
    }
}

class BaseException extends Exception {
    public BaseException(Exception ex){
        super(ex);
    }
    private static final long serialVersionUID = 3987852541476867869L;
}

对这种问题的解决办法一般有两种一种是抛出try语句块中产生的原始异常,忽略在finally语句块中产生的异常。这么做的出发点是try语句块中的异常才是问题的根源。如例:

package test;

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

public class ReadFile {
    public static void main(String[] args) {
        ReadFile rf = new ReadFile();
        try {
            rf.read("F:/manifest_provider_loophole.txt");
        } catch (BaseException2 e) {
            e.printStackTrace();
        }
    }
    public void read(String filename) throws BaseException2 {
        FileInputStream input = null;
        IOException readException = null;
        try {
            input = new FileInputStream(filename);
        } catch (IOException ex) {
            readException = ex;
        } finally {
            if(input != null){
                try {
                    input.close();
                } catch (IOException ex2) {
                    if(readException == null){
                        readException = ex2;
                    }
                }
            }
            if(readException != null){
                throw new BaseException2(readException); 
            }
        }
    }
}

class BaseException2 extends Exception {
    private static final long serialVersionUID = 5062456327806414216L;
    public BaseException2(Exception ex){
        super(ex);
    }
}

另外一种是把产生的异常都记录下来。这么做的好处是不会丢失任何异常。在java7之前,这种做法需要实现自己的异常类,而在java7中,已经对Throwable类进行了修改以支持这种情况。在java7中为Throwable类增加addSuppressed方法。当一个异常被抛出的时候,可能有其他异常因为该异常而被抑制住,从而无法正常抛出。这时可以通过addSuppressed方法把这些被抑制的方法记录下来。被抑制的异常会出现在抛出的异常的堆栈信息中,也可以通过getSuppressed方法来获取这些异常。这样做的好处是不会丢失任何异常,方便开发人员进行调试。如例:

package test;

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

public class ReadFile2 {
    public static void main(String[] args) {
        ReadFile rf = new ReadFile();
        try {
            rf.read("F:/manifest_provider_loophole.txt");
        } catch (BaseException2 e) {
            e.printStackTrace();
        }
    }
    public void read(String filename) throws IOException {
        FileInputStream input = null;
        IOException readException = null;
        try {
            input = new FileInputStream(filename);
        } catch (IOException ex) {
            readException = ex;
        } finally {
            if(input != null){
                try {
                    input.close();
                } catch (IOException ex2) {
                    if(readException != null){
                        readException.addSuppressed(ex2);    //注意这里
                    }else{
                        readException = ex2;
                    }
                }
            }
            if(readException != null){
                throw readException;
            }
        }
    }
}

这种做法的关键在于把finally语句中产生的异常通过 addSuppressed方法加到try语句产生的异常中。

一个catch子句捕获多个异常

在Java7之前的异常处理语法中,一个catch子句只能捕获一类异常。在要处理的异常种类很多时这种限制会很麻烦。每一种异常都需要添加一个catch子句,而且这些catch子句中的处理逻辑可能都是相同的,从而会造成代码重复。虽然可以在catch子句中通过这些异常的基类来捕获所有的异常,比如使用Exception作为捕获的类型,但是这要求对这些不同的异常所做的处理是相同的。另外也可能捕获到某些不应该被捕获的非受检查异常。而在某些情况下,代码重复是不可避免的。比如某个方法可能抛出4种不同的异常,其中有2种异常使用相同的处理方式,另外2种异常的处理方式也相同,但是不同于前面的2种异常。这势必会在catch子句中包含重复的代码。

对于这种情况,Java7改进了catch子句的语法,允许在其中指定多种异常,每个异常类型之间使用“|”来分隔。如例:

package test;

public class ExceptionHandler {
    public void handle(){
        try {
            //..............
        } catch (ExceptionA | ExceptionB ab) { 
        } catch (ExceptionC c) {    
        }
    }
}

这种新的处理方式使上面提出的问题得到了很好的解决。需要注意的是,在catch子句中声明捕获的这些异常类中,不能出现重复的类型,也不允许其中的某个异常是另外一个异常的子类,否则会出现编译错误。如果在catch子句中声明了多个异常类,那么异常参数的具体类型是所有这些异常类型的最小上界。

关于一个catch子句中的异常类型不能出现其中一个是另外一个的子类的情况,实际上涉及捕获多个异常的内部实现方式。比如:

public void testSequence() {
    try {
        Integer.parseInt("Hello");
    } catch (NumberFormatException | RuntimeException e){}
}

比如上面这段代码,虽然NumberFormatException是RuntimeException的子类,但是这段代码是可以通过编译的。但是,如果把catch子句中两个异常的声明位置调换一下,就会出现在编译错误。如例:

public void testSequenceError() {
    try {
        Integer.parseInt("Hello");
    } catch (RuntimeException | NumberFormatException e) {}
}

原因在于,编译器的做法其实是把捕获多个异常的catch子句转换成了多个catch子句,在每个catch子句中捕获一个异常。上面这段代码相当于:

public void testSequenceError() {
    try {
        Integer.parseInt("Hello");
    } catch (RuntimeException e) {
    } catch (NumberFormatException e) {
    }
}


© 著作权归作者所有

共有 人打赏支持
柳哥
粉丝 203
博文 405
码字总数 347782
作品 0
杭州
技术主管
Java7的新特性1-project coin

Project coin project coin是Java一些语法改进的一个项目。 Strings in switch 在Java1.7之前,switch语句只能是byte、char、short和int以及包装类和枚举常量,比如: 在Java7中,扩展了允许...

mushui
2013/07/29
0
4
一起学Java7新功能扩展——深入历险分享(一)

特此声明:因网友疑问,这里声明一个重要的安全,就是大家所知的java惊现0day漏洞!8月30日,Oralce紧急发布了新版本的JDK和JRE,原因是发现了一个严重的0day漏洞CVE-2012-4681,远程攻击者可...

Beyond-Bit
2012/09/03
0
26
深入理解Java 7(笔记)

switch Java 7 中新增加了对String的支持,除此之外还支持int、char、byte、short及其封装类Integer、Character、Byte、Short。对于基本类型的支持我们很容易理解,但是String类型使用了不同...

chris_2009
2016/03/30
103
0
java程序员修炼之道

第一部分:用Java7做开发 第一章:初识java7 1.1语言与平台《Java语言规范(JLP)》《JVM规范(VMSpec)》 1.2Coin项目:浓缩的都是精华 修改过程:1.更新JLS 2.在源码编译器中实现一个原型 3.为修改...

zhchl2010
2015/09/20
83
0
小菜修炼之道——Java7新特性

1、TWR 自动关闭资源 自动关闭资源必须要注意书写规范,所有需要关闭的资源必须使用一个变量声明出来并且写在try的小括号块中,不是大括号。如下代码: try( InputStream is = new FileInpu...

learn_more
2015/08/17
0
0
try-with-resources语句

这节讲的是Java7中引入的使用try语句进行资源管理的新用法。这节的内容与上一节介绍的异常处理的关系比较密切。上节中介绍的Throwable中的新方法addSuppressed就是为try-with-resourcces语句...

柳哥
2014/10/06
0
0
NIO.2特性总结(三)AIO

接上一篇《NIO.2特性总结(二)增强的通道 NetworkChannel》 We’ve finally reached the most powerful feature introduced in NIO.2, the asynchronous channel API. 我觉得第一个问题就是......

Gaischen
2012/12/03
0
4
Ubuntu 12.04 安装 Oracle java

1、删除openJDK sudo apt-get purge openjdk* 2、添加orcale jdk ppa sudo add-apt-repository ppa:eugenesan/java sudo apt-get update 3、安装 sudo apt-get install oracle-java7-instal......

durban
2012/05/15
0
0
java7 WatchServiceDemo 文件系统监控

自己想搞点东西,发现一个java7的新特性蛮好用的,找了一个damo,贴出来希望能帮助到有需要的人。 package com.wanzi.core; import static java.nio.file.StandardWatchEventKinds.ENTRY_CR...

五岳儿爸
2013/05/16
0
1
为什么选择 Java 8 ?

本文是 DZone 指南 Java 生态系统的专题文章。点击链接可阅读更多见解深刻的文章、行业统计信息,系 OneAPM工程师编译整理。 在很多情况下,Java8 都能提升应用性能,而无需任何改变或性能调...

OneAPM蓝海讯通
2015/11/04
117
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

实现服务启动之后,马上执行任务的几种方法

有哪些方法 实现服务启动之后,马上执行相关操作? 方式一 :@PostConstruct 对类的要求 无,普通的java bean即可 例如: /*** * 执行完构造方法之后就会执行该方法 */@PostConstruc...

黄威
17分钟前
0
0
linux服务器修改mtu值优化cpu

一、jumbo frames 相关 1、什么是jumbo frames Jumbo frames 是指比标准Ethernet Frames长的frame,即比1518/1522 bit大的frames,Jumbo frame的大小是每个设备厂商规定的,不属于IEEE标准;...

六库科技
今天
0
0
牛客网刷题

1. 二维数组中的查找(难度:易) 题目描述 在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入...

大不了敲一辈子代码
今天
0
0
linux系统的任务计划、服务管理

linux任务计划cron 在linux下,有时候要在我们不在的时候执行一项命令,或启动一个脚本,可以使用任务计划cron功能。 任务计划要用crontab命令完成 选项: -u 指定某个用户,不加-u表示当前用...

黄昏残影
昨天
0
0
设计模式:单例模式

单例模式的定义是确保某个类在任何情况下都只有一个实例,并且需要提供一个全局的访问点供调用者访问该实例的一种模式。 实现以上模式基于以下必须遵守的两点: 1.构造方法私有化 2.提供一个...

人觉非常君
昨天
0
0
《Linux Perf Master》Edition 0.4 发布

在线阅读:https://riboseyim.gitbook.io/perf 在线阅读:https://www.gitbook.com/book/riboseyim/linux-perf-master/details 百度网盘【pdf、mobi、ePub】:https://pan.baidu.com/s/1C20T......

RiboseYim
昨天
1
0
conda 换源

https://mirrors.tuna.tsinghua.edu.cn/help/anaconda/ conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/conda config --add channels https://mir......

阿豪boy
昨天
1
0
Confluence 6 安装补丁类文件

Atlassian 支持或者 Atlassian 缺陷修复小组可能针对有一些关键问题会提供补丁来解决这些问题,但是这些问题还没有放到下一个更新版本中。这些问题将会使用 Class 类文件同时在官方 Jira bug...

honeymose
昨天
0
0
非常实用的IDEA插件之总结

1、Alibaba Java Coding Guidelines 经过247天的持续研发,阿里巴巴于10月14日在杭州云栖大会上,正式发布众所期待的《阿里巴巴Java开发规约》扫描插件!该插件由阿里巴巴P3C项目组研发。P3C...

Gibbons
昨天
1
0
Tomcat介绍,安装jdk,安装tomcat,配置Tomcat监听80端口

Tomcat介绍 Tomcat是Apache软件基金会(Apache Software Foundation)的Jakarta项目中的一个核心项目,由Apache、Sun和其他一些公司及个人共同开发而成。 java程序写的网站用tomcat+jdk来运行...

TaoXu
昨天
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部