java se7 变化_利用 Java SE 7 异常处理方面的改进

本文介绍Java SE 7中异常处理的改进,包括多重捕获、重新抛出异常及try-with-resources等特性,使代码更简洁且易于维护。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

利用 Java SE 7 异常处理方面的改进 作者:Manfred Riem

了解如何利用改进的异常处理,这是 Java SE 7 中 Coin 项目在语言方面众多有用的小改动中的一个。 2011 年 9 月发布

下载:

简介

在本文中,我们将介绍 Java Platform, Standard Edition 7 (Java SE 7) 版本中的一些变化,Coin 项目)中对此进行了详细说明。我们重点介绍异常处理,具体来说就是多重捕获、重新抛出和 try-with-resources。

Coin 项目由下面这些语言方面的小改动组成,旨在简化常见的日常编程任务: switch 语句中的字符串

更好的整型字符串

本文所介绍的多重捕获异常

改进了泛型实例创建的类型推断(“<>”)

本文所介绍的 try-with-resources

简化了可变参数方法调用

多重捕获异常

Java SE 7 中新增了多重捕获异常,以便更轻松更简洁地处理异常。要将您的异常处理代码从 Java SE 7 之前的代码迁移到 Java SE 7 代码,请继续阅读。 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.

}

}

}

示例 1

过去,如果希望上面三个用例中的两个,比如 ParseException 和 IOException,具有相同的逻辑,您必须复制和粘贴相同的代码。经验不足或懒惰的程序员可能认为像下面这样做就可以了: 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

示例 2 中代码的最大问题在于它可能会带来意想不到的副作用。try 代码块中的任何代码都可能会抛出异常,而该异常将被一个覆盖式 (Exception) catch 子句吞掉。如果抛出的异常不是 ParseException 或 IOException(例如,SecurityException),该代码仍然会捕获它,但上游用户不知道实际发生了什么。像这样吞掉异常会导致很难对问题进行调试。

为了方便程序员工作,Java SE 7 现在包括了多重捕获语句。这就允许程序员将 catch 子句组合成一个代码块,而无需使用危险的 catch-all 子句或复制整个代码块。 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

示例 3 显示了如何将两条语句正确合并成一个 catch 代码块。注意 catch 子句的语法 (ParseException | IOException)。此 catch 子句将同时捕获 ParseException 和 IOException。

因此,如果您现在希望两种不同的异常共享相同的异常处理代码,可以使用管道语法:(ExceptionType| ...| ExceptionType 变量)。

重新抛出异常

执行异常处理时,有时您希望重新抛出已经处理过的异常。经验不足的程序员可能认为以下代码可以完成此操作: 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());

}

}

}

示例 4

但编译器不会编译示例 4 中的代码。示例 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());

}

}

}

示例 5

示例 5 的问题在于它并未真正重新抛出原始异常。而是将其嵌套在另一个异常中,这意味着下游代码需要知道原始异常已被嵌套。因此,为了能够实际捕获原始异常,需要在 Java SE 中进行修改(如示例 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());

}

}

}

示例 6

Try-with-Resources

您可能已注意到示例 1 有一个问题(正因为如此,千万不要在生产环境中不明就理地使用示例代码)。问题是 try 代码块中未清理使用的资源。示例 7 是一个更新版本,说明了在 Java SE 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();

}

}

}

}

}

示例 7

注意,如果曾分配过 BufferedReader,则必须添加一个将其关闭的最终代码块。还应注意到,现在 reader 变量位于 try 代码块之外。如果您想做的只是在发生 I/O 异常时才关闭 reader,那么需要编写很多代码。

在 Java SE 7 中,可以更简洁清晰地完成这一操作,如示例 8 所示。使用新的语法,您可以声明作为 try 块组成部分的资源。这意味着您可以预先定义资源,运行时将在执行 try 代码块后自动关闭这些资源(如果尚未关闭)。 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

注意,在示例 8 中,实际的打开操作发生在 try ( ...) 语句中。请注意,此特性仅对实现了 AutoCloseable 接口的类起作用。

总结

Java SE 7 中的异常处理更改不仅可以让您更简洁地编程(如多重捕获示例中所演示的),还允许您对异常执行部分处理,然后再对其进行调用(如重新抛出示例中所述)。Java SE 7 还能使异常清理操作减少出错,如 try-with-resources 示例中所示。这些特性以及 Coin 项目中提供的其他功能,可以使 Java 开发人员提高工作效率,编写更高效的代码。

另请参见

关于作者

Manfred Riem 在 Systems Made Simple 担任系统架构师。他喜欢使用各种技术。在工作中,他重点关注 Java Platform, Enterprise Edition (Java EE) 技术;而作为业务爱好,他喜欢使用各种语言和工具。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值