java异常——捕获异常+再次抛出异常与异常链

【0】README

0.1) 本文描述+源代码均 转自 core java volume 1, 旨在理解 java异常——捕获异常+再次抛出异常与异常链 的相关知识;


【1】捕获异常相关

1.1)如果某个异常发生的时候没有再任何地方进行捕获, 那程序就会运行终止: 并在控制台上打印出异常信息 , 其中包括异常的类型堆栈的内容;
1.2)要想捕获一个异常, 必须设置 try/catch 语句块:

  • 1.2.1)如果在try语句块中抛出了一个在 catch子句中声明的异常类, 那么
    • case1)程序将跳过try 语句块的其余代码;
    • case2)程序将执行 catch 子句中 的处理器代码;
  • 1.2.2)如果在try语句块中没有抛出任何异常, 那么程序将跳过 catch子句;
  • 1.2.3)如果方法中的任何代码抛出了一个在 catch 子句中没有声明的异常类型, 那么这个方法就会立刻退出;

1.3)看个荔枝: (看一个读取文本的程序代码以演示捕获异常的处理过程)

public void read(String filename)
{try{InputStream in = new FileInputStream(filename);  // 创建输入流int b;while((b=in.read()) != -1)process input}catch(IOException exception){exception.printStackTrace(); // 打印栈轨迹;}
}

对上述代码的分析(Analysis):

  • A1)需要注意的是, try 语句中的大多数代码都很容易理解, 读取并处理文本行, 直到遇到文件结束符为止;(read 方法可能抛出一个IOException异常)
  • A2)在这种情况下, 将跳出整个while循环, 进入 catch子句, 并生成一个 栈轨迹;

1.4)对于一个普通 的程序来说, 处理以上的对异常处理的方法外,还有其他方法吗?

  • 1.4.1)通常, 最好的选择是: 什么也不做, 而是将异常传递给调用者;如果read方法出现了错误, 那就让read方法的调用者去处理。
  • 1.4.2)如果采用这种方式, 就必须声明这个方法可能抛出一个 IOException(将异常传递给调用者);
public void read(String filename) throws IOException
{InputStream in = new FileInputStream(filename);  // 创建输入流int b;while((b=in.read()) != -1)process input
}

Attention)编译器严格地执行 throws 说明符。 如果调用了一个抛出已检查异常的方法, 就必须对它进行处理, 或者将它继续进行传递;
1.5)对于以上两种处理异常的方法, 哪种 方法更好呢?(method1:自己处理(在可能发生异常的函数中添加try/catch 语句块);method2:将异常传递(throw)给调用者,调用者处理)

  • 1.5.1)通常, 应该捕获那些知道如何处理的异常, 而将那些不知道怎么处理的异常继续进行传递;如果想传递一个异常, 就必须在方法的首部添加一个throws 说明符, 以便告知调用者这个方法可能会抛出异常;
  • 1.5.2)阅读API后, 以便知道这个方法可能会抛出哪种异常, 然后再决定是自己处理, 还是添加到 throws 列表中;

Attention)以上规则有个例外: 前面提到, 如果编写一个 覆盖超类的方法, 而这个方法又没有抛出异常, 那么这个方法就必须捕获方法代码中出现的每一个已检查异常。不允许在子类的 throws 说明符中出现超过超类方法所列出的异常类范围;(也就是说父类方法没有抛出异常,你子类方法也不准抛出异常,只能自己添加 try/catch 语句块自己处理)


【2】捕获多个异常

2.1)在一个try 语句块中可以捕获多个异常, 并对不同类型的异常做出不同的处理。可以按照下列方式为每个异常类型使用一个单独的 catch 子句;

try
{}
catch(FileNotFoundException e)
{}
catch(UnknownHostException e)
{}
catch(IOException e)
{}

2.2)要想获得异常对象 的更多信息: 可以试着使用 e.getMessage() 得到详细的错误信息, 或者使用 e.getClass().getName(); 得到异常对象 的实际类型;
2.3)合并catch 子句: 在 java SE7中, 同一个 catch 子句中可以捕获多个异常类型。 例如, 假设对应缺少文件和 未知主机异常的动作是一样的, 就可以合并catch 子句:

try
{}
catch(FileNotFoundException | UnknownHostException e)
{}
catch(IOException e)
{}

Attention)

  • A1)只有当捕获的异常类型彼此间不存在子类关系时 才需要这个特性;
  • A2)捕获多个异常时, 异常变量隐含为 final变量。例如, 不能在以下子句体中为 e 赋不同的 值;
    catch(FileNotFoundException || UnknownHostException e) {}
  • A3)捕获多个异常不仅会让你的代码看起来简单, 还会更高效。生成的字节码只包含一个对应公共catch 子句的代码块;

【3】再次抛出异常与异常链

3.1)在catch子句中可以抛出一个异常, 这样做的目的是 改变异常类型;

  • 3.1.1)看个荔枝:
try
{}
catch(SQLException e)
{throw new ServletException("data error : " + e.getMessage());
}

对以上代码的分析(Analysis):

  • A1)这里, ServletException 用带有异常信息文本的构造器来构造;
  • A2)不过, 可以有一种更好的方法, 并且将原始异常设置为新异常的原因:
try
{}
catch(SQLException e)
{Throwable se = new ServletException("database error");se.initCause(e);throw se;
}
  • A3)当捕获到这个异常时, 就可以使用下面的语句重新得到 原始异常:
Throwable e = se.getCause();

Attention)强烈建议使用这种包装技术, 这样可以让用户抛出子系统中的高级异常, 而不会丢失原始异常的小细节; (推荐使用 strongly recommended)

Hint)

  • H1)如果在一个方法中发生了一个已检查异常,而不允许抛出它, 那么包装技术就十分有用。 我们还可以捕获这个已检查异常, 并将它包装成一个 运行时异常;
  • H2)有时候, 你可能只想记录一个异常,再将它重新抛出, 而不做任何改变:
try
{access the database
}
catch(Exception e)
{logger.log(level, message, e);throw e;
}
  • H3)在Java SE7 之前, 将上述代码放入下述方法中, 会出现一个问题;
public void updateRecord() throws SQLException
  • 因为, java 编译器查看catch 块中的 throw 语句, 然后查看e的类型, 会指出这个方法可以抛出任何Exception而不仅仅是 SQLException;
  • H4)java se 7之后(编译器检测语法合法): 编译器会跟踪到 e 来自于try块中, 假设这个 try 块中仅有 的已检查异常 是 SQLException实例, 另外,假设e在catch块中未改变, 将外围方法声明为 throws SQLException 就是合法的;

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

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

相关文章

java 类似xamarin_xamarin android如何将Java.Lang.Object类型转成C#类型

问题起源其实这个标题也可以换一个更准确一点,因为我遇到的问题是:xamarin android中的Class继承了Java.Lang.Object ,将json序列化成c#类型时发现无法赋值,序列化的格式没问题,但是Class的属性值没有复制成功。xamari…

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

【0】README 0.1) 本文描述源代码均 转自 core java volume 1, 旨在理解 java异常—— finally 子句带资源的 try语句 的相关知识; 【1】 finally 子句相关 1.1)产生资源回收问题:当代码抛出一个异常时, …

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…