Java SE 7 Exception的使用
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推荐