JDK1.7新特性(2):异常和可变长参数处理

异常

jdk1.7对try--catch--finally的异常处理模式进行了增强,下面我们依次来看增强的方面。

  1. 为了防止异常覆盖,给Throwable类增加了addSuppressed方法,可以将一个异常信息追加到另一个异常信息之后:

 1     /**
 2      * 这是第一种防止前面异常被覆盖的方法,通过在finally块中判断前面是否有异常抛出
 3      * 如果有则最终抛出的异常为原来的异常,没有则最终抛出的异常为finally块中的异常。
 4      * 此时只能抛出一种异常信息。
 5      * @param fileName
 6      */
 7     private void readFile(String fileName) {
 8         FileInputStream input = null;
 9         IOException readException = null;
10         try {
11             input = new FileInputStream(fileName);
12         } catch (IOException ex) {
13             readException = ex;
14         } finally {
15             if (input != null) {
16                 try {
17                     input.close();
18                 } catch (IOException e) {
19                     // 如果前面没有出现异常,则说明整个异常是此处产生的
20                     if (readException == null) {
21                         readException = e;
22                     }
23                 }
24             }
25             
26             if (readException != null) {
27                 throw new RuntimeException(readException);
28             }
29         }
30     }
31     
32     /**
33      * 这是第二种防止异常被覆盖的方法,利用jdk7的新特性。通过在finally块的异常捕获代码中判断前面是否抛出异常,如果抛出异常
34      * 则将finally块中抛出的异常追加在前面的异常信息之后。这样同时可以抛出两种异常信息类型。
35      * @param fileName
36      */
37     private void readFile2(String fileName) {
38         FileInputStream input = null;
39         IOException readException = null;
40         try {
41             input = new FileInputStream(fileName);
42         } catch (FileNotFoundException e) {
43             readException = e;
44         } finally {
45             if (input != null) {
46                 try {
47                     input.close();
48                 } catch (IOException e) {
49                     // 如果前面抛出的异常不为空,这里将finally块中的异常信息添加到原异常信息后面
50                     if (readException != null) {
51                         readException.addSuppressed(e);
52                     } else {
53                         readException = e;
54                     }
55                 }
56             }
57             if (readException != null) {
58                 throw new RuntimeException(readException);
59             }
60         }
61     }

  2. catch块增强,可以同时捕获多个异常,来进行统一的处理:

 1     /**
 2      * 这里测试jdk7的新特性,一个catch语句中可以捕获多种异常,以 | 分割。
 3      */
 4     private void catchMore() {
 5         // 在jdk1.7新特性这本书中说一个catch块中可以同时捕获属于父子关系的异常(只要子在前父在后,同分开的catch块中的顺序),但实际上在jdk1.8中时不允许的。
 6         try {
 7             int a = Integer.valueOf("aaa");
 8             throw new IOException();
 9         }  
10         /*
11             会报NumberFormatException已经被捕获
12             catch (NumberFormatException | RuntimeException | IOException e) {
13             
14         }*/ catch (NumberFormatException | IOException e) {
15             
16         } catch (RuntimeException e) {
17         }
18     }

  3. throw语句增强,异常在第二次抛出之后,仍然能够准确的知道最原始的异常类型:

 1     /**
 2      * jdk1.7之后,即使异常被重新抛出,编译器也知道原始异常类型,而不会被再抛出的异常类型所干扰。
 3      * 如果在jdk1.6或者之前的版本,第二个catch只能是ExceptionA,因为原始的ExceptionASub2被抹去了。
 4      */
 5     private void testRecatch() {
 6         try {
 7             throw new ExceptionASub2();
 8         } catch (ExceptionA e) {
 9             try {
10                 throw e;
11             } catch (ExceptionASub2 e2) {   // 如果是catch (ExceptionASub1 e2) 那么会报编译错误,因为编译器知道原始异常是ExceptionASub2
12                 
13             }
14         }
15     }
16 
17 class ExceptionA extends Exception {}
18 class ExceptionASub1 extends ExceptionA {}
19 class ExceptionASub2 extends ExceptionA {}

  4. try语句增强,try块可以进行资源管理:

 1     /**
 2      * jdk1.7之后,对try块进行了增强,使其中声明的资源总是可以正确的被释放,而不需要多余的finally块来单独处理。
 3      * 这有点像python的 with open("a.txt") as file 语句一样。
 4      * 需要注意的是,此时资源必须实现AutoCloseable接口,实际上jdk1.7中通过
 5      * public interface Closeable extends AutoCloseable,将Closeable继承于AutoCloseable接口。
 6      * 如果我们要自己实现资源的关闭,只需直接实现AutoCloseable接口即可。
 7      */
 8     private void tryWithResource() {
 9         String fileName = "a.txt";
10         try (BufferedReader br = new BufferedReader(new FileReader(fileName))) {
11             
12         } catch (FileNotFoundException e) {
13             
14         } catch (IOException e) {
15             
16         }
17     }

变长参数

jdk1.7在变长参数和范型结合使用的时候,增加了一个@SafeVarargs。通过该注解来告诉编译器参数类型的安全性,以此来解决每次调用都出现编译警告的问题。

 1     /**
 2      * 在jdk1.7之前,需要使用@SuppressWarnings("unchecked")注解来给每一个调用该方法的地方取消警告
 3      * 。这是因为变长参数的实际值时通过数组来传递的,而数组中传递的时不可具化的范型对象,自身存在类型安全问题,所以编译器
 4      * 会给出警告。这在调用java.utils.Arrays.asList方法和java.util.Collections.addAll方法中也会遇到。
 5      * jdk1.7中提供了在该方法声明的地方加上@SafeVarargs注解。来表示该方法在与范型结合使用的时候不会出现类型安全问题。
 6      * 此时再调用该方法,编译器不会给出警告信息。
 7      * 不过需要注意的是,该方法必须声明为static或者final方法,否则会出现编译错误。
 8      */
 9     @SafeVarargs
10     public static<T> T useVarargs(T... args) {
11         return args.length > 0 ? args[0] : null;
12     }

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏LanceToBigData

OOAD-设计模式(四)结构型模式之适配器、装饰器、代理模式

前言   前面我们学习了创建型设计模式,其中有5中,个人感觉比较重要的是工厂方法模式、单例模式、原型模式。接下来我将分享的是结构型模式! 一、适配器模式 1.1...

1809
来自专栏Java技术栈

揭开Java 泛型类型擦除神秘面纱

大家可能会有疑问,我为什么叫做泛型是一个守门者。这其实是我个人的看法而已,我的意思是说泛型没有其看起来那么深不可测,它并不神秘与神奇。泛型是 Java 中一个很...

694
来自专栏Kevin-ZhangCG

[ Java学习基础 ] Java异常处理

2196
来自专栏java达人

设计模式之代理模式(二)CGLIB动态代理实现

像上一篇所说的代理模式其实是静态代理,在实际开发中其实应用不大,因为他需要事先知道被代理对象是谁,而且被代理对象和代理对象实现了公共的接口。实际情况往往并不能满...

18210
来自专栏程序猿DD

Spring Cloud实战小贴士:Zuul统一异常处理(一)

在上一篇《Spring Cloud源码分析(四)Zuul:核心过滤器》一文中,我们详细介绍了Spring Cloud Zuul中自己实现的一些核心过滤器,以及这...

2666
来自专栏成猿之路

MyBatis拦截器原理探究

MyBatis提供了一种插件(plugin)的功能,虽然叫做插件,但其实这是拦截器功能。那么拦截器拦截MyBatis中的哪些内容呢?

682
来自专栏JavaQ

深入浅出JDK动态代理(一)

何为代理 代理,即代替主角完成一些额外的事情。例如,明星都有经纪人,明星参演电影之前,经纪人作为明星的代理人和出资方洽谈片酬、排期等,而真正参与拍戏的还是明星本...

3194
来自专栏java思维导图

揭开Java 泛型类型擦除神秘面纱

大家可能会有疑问,我为什么叫做泛型是一个守门者。这其实是我个人的看法而已,我的意思是说泛型没有其看起来那么深不可测,它并不神秘与神奇。泛型是 Java 中一个很...

543
来自专栏Google Dart

Dart服务器端 shelf包 原

handler是处理shelf.Request并返回shelf.Response的任何函数。它可以处理请求本身 - 例如,在文件系统上查找请求的URI的静态文件...

971
来自专栏JMCui

浅析 SpringMVC 原理和配置.

一、原理       Spring MVC基于模型-视图-控制器(Model-View-Controller,MVC)模式实现,它能够帮你构建像Spring框架...

3589

扫码关注云+社区