java异常—— finally 子句+带资源的 try语句

【0】README

0.1) 本文描述+源代码均 转自 core java volume 1, 旨在理解 java异常—— finally 子句+带资源的 try语句 的相关知识;


【1】 finally 子句相关

1.1)产生资源回收问题:当代码抛出一个异常时, 就会终止方法中剩余代码的处理, 并退出这个方法的执行。如果方法获得了一些本地资源,且只有这个方法知道, 那么就会产生资源回收问题;
1.2)解决方法:

  • 1.2.1)一种解决方法是 捕获并重新抛出所有异常: 但是, 这种方法比较乏味, 因为需要在两个地方取出所有分配的资源;
  • 1.2.2)一种更好的解决方法是 finally 子句;

1.3)看个荔枝(不管是否异常被捕获, finally子句都会被执行),在下面的示例中, 程序将在所有cases 下关闭文件:

InputStream in = new FileIinputStream();
try
{
//1
code that might throw exceptions
//2
}
catch(IOException e)
{
//3
show error msg
//4
}
finally
{// 5in.close();
}
//6

对以上代码的分析(Analysis)(在上面的 代码中, 有下列3种cases 会执行finally 子句):

  • A1)代码没有抛出异常。在这种情况下, 程序首先执行try语句块中的全部代码, 然后执行 finally子句中的代码。随后执行try语句块之后的 第一条语句, 执行顺序为1、2、5、6;

  • A2)抛出一个在catch 子句中捕获的异常。

    • A2.1)如果catch子句没有抛出异常, 程序将执行try 语句块之后的第一条语句, 在这里的执行顺序为 1、3、4、5、6;
    • A2.2)如果catch 子句抛出异常, 异常将被抛出这个方法的调用者, 在这里, 执行顺序为 1、3、5;
  • A3)代码抛出了一个异常, 但catch 子句无法捕获; 在这里, 执行顺序为 1、5;

1.4)try语句可以只有 finally子句,而没有catch子句:如,

InputStream in = "...";
try
{}
finally
{in.close();
}
  • 1.4.1)无论在try 语句块中是否遇到异常,finally子句中的 in.close() 语句都会被执行, 当然, 如果真的遇到一个异常, 这个异常将会被重新抛出, 并且必须由另一个catch 子句捕获;
  • 1.4.2)我们在需要关闭资源的时候, 用这种方式使用 finally 子句是一个不错 的选择;

Hint)这里, 强烈建议独立使用 try/catch 和 try/finally 语句块, 可以提高代码的清晰度。如,(强烈推荐-strongly recommended)

InputStream in = "...";
try
{try{code that might throw exceptions}    finaly{in.close();}    
}
catch(IOException e)
{show error msg
}
  • H1)内层的try语句块有一个职责, 就是确保关闭输入流;
  • H2)外层的try 语句块也只有一个职责, 就是确保报告出现的错误;
  • H3)这种设计不仅清楚, 而且还将报告finally子句中出现的错误;

Warning)

  • W1)当finally子句包含 return 语句时, 将会出现一种意想不到的结果;
  • W2)假设利用return 语句从try 语句块中退出。 在这个方法返回前, finally子句的内容将被执行;

1.5)如果finally子句也有一个 return, 这个返回值将会覆盖原始的返回, 看个荔枝

public static int f(int n)
{try{int r = n * n;return r;}finally{if(n==2) return 0;}
}

对上述代码的分析(Analysis):如果调用 f(2),那么try语句块return 4, 而方法返回前, 还要执行 finally子句, 其返回0, 这个返回值会覆盖掉原始的返回值4**(即最终的返回值是0 而不是4);**

1.6)出现的问题:

InputStream in = "...";
try
{code that might throw exceptions
}
finally
{in.close();
}
  • 1.6.1)问题描述:对于上述代码, 假设在 try 语句块中的代码抛出了 IOException异常, 这些异常只有这个方法的调用者才能够处理。 执行finally语句块, 并调用close 方法。 而 close 方法本身也可能抛出 IOException异常。 当出现这种case 时, 原始的异常数据将丢失, 转而抛出 close 方法的异常;
  • 1.6.2)解决方法: 如果你想做适当处理的话, 重新抛出原来的异常,代码会变得极其繁琐;如下图所示:
InputStream in = "...";
Exception ex = null;
try
{try{code that might throw exceptions}        catch(Exception e){ex = e;throw e;}
}
finaly
{try{in.close();}catch(Exception e){if(ex == null) throw e;}
}    

【2】 带资源的 try语句

2.1)对于以下代码模式:

open a resource
try
{work with the resource
}
finally
{close the resource
}
  • 2.1.1)假设资源属于一个实现了 AutoCloseable 接口的类, AutoCloseable 接口有一个方法:
void close()  throws Exception;

Annotation)还有一个 Closeable 接口, 它是 AutoCloseable 的子接口, 也包含一个 close方法, 不过, 这个方法声明为抛出一个 IOException;
2.2)带资源的 try语句(try-with-resource)的最简单形式为:

try(Resource res)
{work with  res
}
  • 2.2.1)try块退出时, 会自动调用 res.close()。看个荔枝——读取一个文件中的所有单词:
try(Scanner in = new Scanner(new FileInputStream("/usr/.../")))
{while(in.hasNext())System.out.println(in.next());
}
  • 上述代码中的 try块正常退出时, 或者存在一个异常时, 都会调用 in.close()方法, 就好像使用了 finally块一样;
  • 2.2.2)还可以指定多个 资源:
try(Scanner in = new Scanner(new FileInputStream("/usr/.../")), PrintWriter out = new PrintWriter("out.txt"))
{while(in.hasNext())out.println(in.next().toUpperCase());
}
  • 2.2.3)无论这个块如何退出, in 和 out 都会关闭: 如果你使用常规方式手动编程,就需要两个嵌套的 try/finally 子句;

Conclusion)

  • C1)我们看到, 如果try块中抛出一个异常, 而且close方法也抛出一个异常, 这就会带来一个难题, 现在 带资源的try块解决了这个问题;
  • C2)原来的异常会被重新抛出, 而 close方法抛出的异常会“被抑制”;
  • C3)这些异常将自动捕获, 并由 addSuppressed 方法增加到原来的异常。如果对异常有兴趣, 可以调用 getSuppressed 方法, 它会得到从 close方法 抛出并被抑制的异常列表;

Attention)只要需要关闭资源, 就要尽可能地使用带资源的 try语句;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/331788.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

jep290涉及jdk版本_JDK 13中的JEP 355文本块

jep290涉及jdk版本JDK 13已于2019年9月17日上线GA, 此处列出了重要的新功能。 新功能之一是“文本块”。 这样可以轻松地编写多行字符串,而不必在拆分为不同行的同时进行串联。 让我们快速了解创建多行字符串的不同方式: String aBlock &q…

java单例注册表_Java单例模式(Singleton)

单例模式主要用于:有一些对象我们只需要一个,比如:线程池、缓存、对话框、处理偏好设置、注册表对象、日志对象以及配置文件对象、数据库连接对象等等。单例模式常用于管理共享资源,例如:数据库连接或者线程池。Java S…

java异常——分析堆栈跟踪元素+使用异常机制的技巧

【0】README 0.1) 本文描述源代码均 转自 core java volume 1, 旨在理解 java异常——分析堆栈跟踪元素使用异常机制的技巧 的相关知识; 【1】分析堆栈跟踪元素相关 1.1)堆栈跟踪: 它是一个方法调用过程的列表&#…

jdk8 npe_JDK 14中更好的NPE消息

jdk8 npe我的2019年3月博客文章“ Java会出现更好的默认NullPointerException消息吗? ”的撰写是为了获得更好的NullPointerException消息的JEP 草案尚未针对特定的JDK版本。 此后,该JEP草案成为JEP 14的 目标 JEP 358(“ Helpful NullPointe…

开源相册系统Java_基于JAVA的B/S网络相册管理系统

每天记录学习,每天会有好心情。*^_^*今天和一个朋友共同完成了一个网络相册管理系统项目,我们在开发时选用的框架是SSM(MYECLIPSE)框架。我这个朋友知识有限,只会这个框架,哈哈,都是为了方便他。和往常一样选用简单又便…

java断言——Assertion

【0】README 0.1) 本文描述源代码均 转自 core java volume 1, 旨在理解 java断言——Assertion 的相关知识; 【1】使用断言 1.1)断言机制: 允许在测试期间向代码中插入一些检查语句。 当代码发布时, 这些…

常见的并发模型_两个常见的并发错误

常见的并发模型作为Baeldung的编辑,我很高兴与一位作者一起撰写有关Java通用并发陷阱的文章。 这是一本不错的书,但是假设开发人员具有一定的能力。 我已经看到了几件即时并发失败的事情。 它们很容易添加到代码中,并保证为您提供奇怪的结果…

java 哈希一致算法_一致哈希算法Java实现

一致哈希算法(Consistent Hashing Algorithms)是一个分布式系统中常用的算法。传统的Hash算法当槽位(Slot)增减时,面临所有数据重新部署的问题,而一致哈希算法确可以保证,只需要移动K/n份数据(K为数据总量, n为槽位数量),且只影响…

java日志——基本日志+高级日志

【0】README 0.1) 本文描述源代码均 转自 core java volume 1, 旨在理解 java日志——基本日志高级日志 的相关知识; 【1】记录日志 1.1)出现的问题和解决方法: 1.1.1)出现的问题:在我们调试…

java模式匹配_用Java匹配模式

java模式匹配如果您使用的是Java,那么您很有可能以前已经看过它的模式匹配。 String#matches(String)方法在内部使用Pattern类型,该类型包含更复杂的功能: 通过编译正则表达式来创建Pattern 。 该模式与任何输入字符串匹配,并且可…

java在frame怎么计时_java – 退出jframe时的Swing stop计时器

我有一个特定的任务,我按计划的时间间隔运行.基本上我在JFrame中的Label上显示相机.但是,当我退出JFrame时,应用程序似乎运行.我怎么能阻止它?我已经删除了代码的细节,只是将相关部分留在了public class TaskCLass extends JFrame {JPanel p;JLabel l;Timer timer;p…

java日志——修改日志管理器配置+日志本地化

【0】README 0.1) 本文描述源代码均 转自 core java volume 1, 旨在理解 java日志——修改日志管理器配置日志本地化 的相关知识; 【1】修改日志管理器配置 1.1)可以通过编辑配置文件来修改日志系统的各种属性。 在默认情况下&a…

jpa embedded_JPA @Embeddable和@Embedded

jpa embedded介绍: 作为一个面向对象的开发人员,我们希望避免使用带有大量不相关字段的大型类。 因此,我们可能经常感到有必要使用多个对象来表示JPA实体。 在本快速教程中,我们将学习如何使用JPA或Hibernate中的Embedded和Embed…

jdk内置线程实例_EA问题的JDK14实例

jdk内置线程实例Tagir Valeev最近发布了一条有关即将发布的Java JDK14版本的预览功能的推文: #Java14模式匹配将名称隐藏带入了更高的疯狂程度。 在这里,我为FLAG字段添加或删除了final修饰符,该修饰符仅在不可达的if分支中访问。…

intro to Apache Log4j 2

【0】README 0.1)本文作为 原文(http://logging.apache.org/log4j/2.x/)的译文,仅作参考, 旨在了解 Log4j 2 的相关知识 ; 0.2) Apache Log4j 2 是Log4j的升级版,并对其前任Log4j …

php注册页面模板,选项卡式WordPress登陆注册模板

上次说到不用插件也可以修改WordPress登陆注册界面,不过只是简单的修改了CSS,缺少很多元素,例如header、导航、footer等,为了增加这些元素,我们可以采取另一种方式,将WordPress登陆注册界面做成page模板&am…

内核堆栈 用户堆栈_弹性堆栈介绍

内核堆栈 用户堆栈当您运行对公司至关重要的软件时,您将无法拥有仅用于分析一段时间前发生的事情的日志,让客户端告诉您您的应用程序已损坏,而您甚至不知道发生了什么是真实的问题。 解决该问题的方法之一是使用监视和日志记录。 大多数应用…

php 字符串 中文,php 中文字符串截取乱码

PHP截取字符串如果是英文直接用substr就可以了,但对于中文字符,用substring可能会导致乱码,那么将如何解决呢?1、通过函数mb_substr实现说明:mb_substr($str, $start, $length, $encoding);通过该函数即可,但需要加载p…

java 调试技巧

【0】README 0.1) 本文描述源代码均 转自 core java volume 1, 旨在理解 java 调试技巧 的相关知识; 【1】调试技巧相关 1.1)可以用下面的方法打印或记录任意变量的值: System.out.println("x " x); 或 …

jdk 版本和内部版本对应_JDK 14 Rampdown:内部版本27

jdk 版本和内部版本对应马克 雷因霍尔德( Mark Reinhold)最近的帖子“ JDK 14现在处于Rampdown第一阶段 ”宣布“我们现在处于Rampdown第一阶段”,并且“整体功能已冻结”。 JDK 14 Early Access Build #27(2019/12/12…