Java SE 7 Exception的使用

标签: java se exception | 发表时间:2012-03-01 01:23 | 作者:
出处:http://www.iteye.com

Java SE 7 Exception的使用

在Java SE 7 中,作为Project Coin项目中众多有用的细小语言变化之一的加强型异常处理,现在来学习如何利用它。

简介:

在这边文章中,我们所涉及的一些变化是作为Java平台标准版7(Java SE 7)所发布,在JSR334(Java Specification Request)有详细的说明。现在我们重点讨论异常处理,特别是:multi-catch,rethrow,以及try-with-resources.

 

Multi-Catch Exceptions

多异常捕获已经加入到Java SE 7,他帮助我们更简便的进行异常处理,现在就把你的异常处理代码从Java SE7之前的版本迁移到Java SE7来阅读。

1

 

public class ExampleExceptionHandling
{
   public static void main( String[] args )
   {
   try {
        URL url = new URL("http://www.yoursimpledate.server/");
        BufferedReader reader = new
              BufferedReader(newInputStreamReader(url.openStream()));
        String line = reader.readLine();
        SimpleDateFormat format = new SimpleDateFormat("MM/DD/YY");
        Date date = format.parse(line);
   }
   catch(ParseException exception) {
        // handle passing in the wrong type of URL.
   }
   catch(IOException exception) {
        // handle I/O problems.
   }
   catch(ParseException exception) {
        // handle date parse problems.
   }
   }
}
 

 

在过去,如果你想要相同的逻辑代码在上面的三个异常代码块的时候,你不得不在PaseException和IOException中拷贝粘贴代码,一个缺乏经验或者懒惰的程序员可能认为像下面这样也是OK的。

2

 

public class ExampleExceptionHandlingLazy
{
   public static void main( String[] args )
   {
         try {
                  URL url = new URL("http://www.yoursimpledate.server/");
                  BufferedReader reader = new
             BufferedReader(new InputStreamReader(url.openStream()));
                  String line = reader.readLine();
                  SimpleDateFormat format = new SimpleDateFormat("MM/DD/YY");
                  Date date = format.parse(line);
         }
         catch(Exception exception) {
                  // I am an inexperienced or lazy programmer here.
         }
   }
}
 

 

在例2代码示例中最大的毛病就是会产生不可预料的副作用,任何代码在try代码块可能产生异常,所有异常将全部由catch子句所处理。如果一个异常既不是ParseException也不是IOException(例如:SecurityException),此异常仍然会被捕获,但是上游用户去不知道真正发生了什么?这种吞并式的异常将很难调试。

 

为了方便程序员,JavaSE7现在引入了多异常捕获,这样程序员就可以合并多个catch字句为一个单独的代码块,而不需要去使用危险的吞并似的一个异常捕获所有,或者拷贝整个代码块。

例3:

 

public class ExampleExceptionHandlingNew
{
   public static void main( String[] args )
   {
         try {
                  URL url = new URL("http://www.yoursimpledate.server/");
                  BufferedReader reader = new BufferedReader(
                           new InputStreamReader(url.openStream()));
                  String line = reader.readLine();
                  SimpleDateFormat format = new SimpleDateFormat("MM/DD/YY");
                  Date date = format.parse(line);
         }
         catch(ParseException | IOException exception) {
                  // handle our problems here.
         }
   }
}
 

 

示例3就展示了怎么合理的合并两个catch块语句,注意catch子句的语法(ParseException|IOException),catch子句可以捕获ParseException和IOException。所以如果想多个不同的异常共用相同的异常处理代码,那么就可以使用这种管道语法(ExceptionType…|ExceptionType variable)。

 

Rethrowing Exceptions

当你在处理异常的时候,有时候想把一个处理完后的异常往外抛的时候,没有经验的程序员可能认为用下面这种方式操作是合理的

例4

 

public class ExampleExceptionRethrowInvalid
{
   public static void demoRethrow()throws IOException {
         try {
                  // forcing an IOException here as an example,
                 // normally some code could trigger this.
                 throw new IOException(“Error”);
         }
         catch(Exception exception) {
                  /*
                   * Do some handling and then rethrow.
                   */
                  throw exception;
         }
   }
   
   public static void main( String[] args )
   {
         try {
                  demoRethrow();
                  }
         catch(IOException exception) {
         System.err.println(exception.getMessage());
         }
   }
}
 

很遗憾的是编译器没发完成编译工作,下面这段代码展示了如何去处理完异常后再往外抛。

例5

 

public class ExampleExceptionRethrowOld
{
   public static demoRethrow() {
         try {
                  throw new IOException("Error");
         }
         catch(IOException exception) {
                  /*
                   * Do some handling and then rethrow.
                   */
                  throw new RuntimeException(exception);
         }
   }
   
   public static void main( String[] args )
   {
         try {
                  demoRethrow();
         }
         catch(RuntimeException exception) {
         System.err.println(exception.getCause().getMessage());
         }
   }
}
 

上面这个例子的毛病就在于不能抛出原生的异常,他用另外一个异常包裹了,这就意味着代码的下游需要注意他是被包装了的。所以为了捕获到这个确切的原生异常,在Java SE7中做出变化是必须的,如下代码:

例6

 

public class ExampleExceptionRethrowSE7
{
   public static demoRethrow() throws IOException {
         try {
                  throw new IOException("Error");
         }
         catch(Exception exception) {
                  /*
                   * Do some handling and then rethrow.
                   */
                  throw exception;
         }
   }
   
   public static void main( String[] args )
   {
         try {
                  demoRethrow();
         }
         catch(IOException exception) {
         System.err.println(exception.getMessage());
         }
   }
}
 

上面的示例在JavaSE7中能正确的编译(译者注)

 

Try-with-Resources

你可能注意到了在第一个例子中有这样一个问题(这就是为什么当你不知道示例代码做了些什么的时候,你永远也不要在生产环境中使用)。这个问题就是没有对资源的清空。例7是一个修改的版本,描述了怎样在JavaSE7之前的版本中校正这个问题。

例7

 

public class ExampleTryResources
{
   public static void main(String[] args)
   {
         BufferedReader reader = null;
   
         try {
                  URL url = new URL("http://www.yoursimpledate.server/");
                  reader = new BufferedReader(new 
                                   InputStreamReader(url.openStream()));
                  String line = reader.readLine();
                  SimpleDateFormat format = new SimpleDateFormat("MM/DD/YY");
                  Date date = format.parse(line);
         }
         catch (MalformedURLException exception) {
                  // handle passing in the wrong type of URL.
         } catch (IOException exception) {
                  // handle I/O problems.
         } catch (ParseException exception) {
                  // handle date parse problems.
         } finally {
                  if (reader != null) {
                           try {
                                   reader.close();
                                    } catch (IOException ex) {
                                   ex.printStackTrace();
                           }
                  }
         }
   }
}
 

我们注意到代码中添加了一个final代码块,如果BufferedReader被赋值了,它将被关闭,而且变量reader也已经移到了try代码块的外面了。当一个I/O异常发生的时候关闭字符流就要多些很多的代码。

 

在JavaSE7中,可以更简洁更清爽,如例8所示,这种新的语法允许你把资源作为try代码块的一部分,这意味着可以提前定义好资源然后执行完try代码块的时候虚拟机将自动关闭资源。

例8

 

public static void main(String[] args)
{
   try (BufferedReader reader = new BufferedReader(
         new InputStreamReader(
         new URL("http://www.yoursimpledate.server/").openStream())))
   {
         String line = reader.readLine();
         SimpleDateFormat format = new SimpleDateFormat("MM/DD/YY");
         Date date = format.parse(line);
   } catch (ParseException | IOException exception) {
         // handle I/O problems.
   }
}
 

在例8中实际发生变化的是在try(….)语句,需要注意的是这个特性只有在资源实例实现了AutoCloseable接口的实例才能生效

 

总结:

异常处理在javaSE7中,你不仅可以写出更简洁的程序,正如multi-catch示例所演示的一样,而且在可以处理完部分异常后再往外抛出去。如re_throw 例子所示,JavaSE7同样有助于减少易于出错的异常清理。正如我们在try-with resource例子中看到的一样。这些特征和其他Project Coin项目中提供的一样,能使Java程序员写代码更有效率以及写出更高效的代码。

 

附上自己的一点感受:第一次这样认真的去翻译一遍文章,以往看完一遍文章可以不到二十分钟,但是翻译工作花了我两个小时,非常认真的在做,发现翻译不仅可以学外语,还可以学语文。对自己的语言组织也有提高,终于体会到翻译书籍的人特别不容易。 2012/3/1  1:20

 

原文连接 http://www.oracle.com/technetwork/articles/java/java7exceptions-486908.html

 



已有 0 人发表留言,猛击->> 这里<<-参与讨论


ITeye推荐



相关 [java se exception] 推荐:

Java SE 7 Exception的使用

- - ITeye博客
Java SE 7 Exception的使用. 在Java SE 7 中,作为Project Coin项目中众多有用的细小语言变化之一的加强型异常处理,现在来学习如何利用它. 在这边文章中,我们所涉及的一些变化是作为Java平台标准版7(Java SE 7)所发布,在JSR334(Java Specification Request)有详细的说明.

Java SE 7发布

- Jingzhi - Solidot
甲骨文宣布发布Java SE 7,这是Java在甲骨文名下发布的第一个版本. 开发者在博客上称它是五年全世界Java社区协助成果,是Java发展中的重要一步. Java SE 7主要新特性包括:Project Coin,提高生产力,简化编程任务;Fork/Join Framework,支持多核心处理器,简化问题分解并行执行;InvokeDynamic,使其它语言能更容易的在JVM中运行.

消除Java应用中的Exception开销

- - 舒の随想日记
抛异常最大的消耗在于构造整个异常栈的过程,如果你的栈很深,特别是用了一些框架的话,这个开销基本是不可忽视的,之前做的一个优化显示当时应用中的一个异常使得整个应用的性能下降至少30%. 最大开销的地方在这里,当你去new一个Exception的时候,会调用父类Throwable的构造函数, Throwable的构造函数中会调用native的fillInStackTrace(),这个方法就会构造整个异常栈了.

Java的Exception和Error面试题10问10答

- - ITeye博客
JAVA 中Exception和Error 面试问题.   下面是我个人总结的在Java和J2EE开发者在面试中经常被问到的有关Exception和Error的知识. 回答的时候,我也给这些问题作了快速修订,并且提供源码以便深入理解. 我总结了各种难度的问题,适合新手码. 如果你遇到了我列表中没有的问题,并且这个问题非常好,请在下面评论中分享出来.

该如何良好的实践Java中的Exception机制

- - BlogJava-首页技术区
首先,我先声明一点,我讨论的仅限于互联网数据产品,当然可能会涉及到一些其他的抽象,但是所有的结论不代表能复用到所有场景.         几乎每个Java程序员都清楚知道Java的异常和错误机制,无论是在面试过程中,还是在学习中,你看到Exception,无非就是了解一下继承关系、子类、和Error的关系等等.

[译]Java中9个处理Exception的最佳实践

- - 后端技术杂谈 | 飒然Hang
在Java中处理异常并不是一个简单的事情. 不仅仅初学者很难理解,即使一些有经验的开发者也需要花费很多时间来思考如何处理异常,包括需要处理哪些异常,怎样处理等等. 这也是绝大多数开发团队都会制定一些规则来规范对异常的处理的原因. 而团队之间的这些规范往往是截然不同的. 本文给出几个被很多团队使用的异常处理最佳实践.

Java SE 6 故障排除指南 – 3、内存泄露

- - 码蜂笔记
如果你的应用程序执行的时间越来越长,或如果操作系统执行越来越慢,这可能是内存泄露的指示. 换句话说,虚拟内存被分配但在不需要时没有归还. 最终应用程序或系统没有可用内存,应用程序非正常终止. 这篇文章提供了一些涉及内存泄露的问题诊断的建议. 3.1 OutOfMemoryError 的含义. 一个最常见的内存泄露的指示是 java.lang.OutOfMemoryError 错误.

利用Java SE 8流处理数据II(译)

- - BlogJava-首页技术区
利用Java SE 8流处理数据. -- 结合Stream API的高级操作去表示富数据处理查询. 本文是 Java Magazine 201405/06刊中的一篇文章,也是文章系列"利用Java SE 8流处理数据"中的第二篇,它基于flatMap()和collect()介绍了Java流的高级用法(2014.08.15最后更新).

[译]Java SE 8 新特性之旅 : Java开发世界的大变动

- - 上善若水 厚德载物
我很自豪的成为了adopt-OpenJDK的一员,像其他专业团队成员一样,但是我只刚加入了8个月,我们一同经历了Java SE 8 的开发、编译、编码、讨论……等等,直到JDK上线. Java SE 8发布于2014年3月18日,现在可供下载使用. 我很高兴发布这一系列“Java SE 8 新特性之旅”,我会写一些例子来简化Java SE 8知识的获取、开发经验、新特性和API,然后.

Java SE 6 故障排除指南 – 4、系统崩溃故障排除

- - 码蜂笔记
崩溃或致命错误导致进程异常终止. 例如,崩溃可能是由于HotSpot VM、系统库、Java SE 库或API、程序本地代码、甚至操作系统里的 bug. 极端因素如操作系统资源耗尽也可以导致崩溃. 因 HotSpot VM 或 Java SE库代码导致的崩溃是罕见的. 有时候可以变通崩溃直到导致崩溃的源被诊断和修复(也就是可以避开崩溃).