[02] 异常链和自定义异常

1、异常链

1.1 throw

我们之前比喻过,说异常的抛出就像棒球中的投球,其中RuntimeException是发生意外后程序自行抛出的,假如我们想要自己抛出异常,就要使用 throw 关键字。

显式地抛出异常通常写为:

  1. throw new xxxException();

异常抛出后,有两种处理方式:

  • 立即处理,使用 try catch 捕获并处理
  • 稍后处理,丢给方法调用的上层处理,使用 throws 关键字
  1. //try-catch 立即处理
  2. public static void fun() {
  3. File file = new File("C:/temp.txt");
  4. if (!file.exists()) {
  5. try {
  6. throw new IOException();
  7. } catch (IOException e) {
  8. System.out.println("文件不存在");
  9. }
  10. }
  11. }
  1. //throws 稍后处理
  2. public static void fun() throws IOException{
  3. File file = new File("C:/temp.txt");
  4. if (!file.exists()) {
  5. throw new IOException();
  6. }
  7. }

使用throw抛出异常时,不要直接使用Exception,或者相互之间有交集的异常,这样不能很好地标记异常的类型,增加了后期维护难度。

另外,在进行方法覆盖的时候要注意,假如你的某个方法覆盖了父类的某个方法,那么:

  • 不可以增加新的异常,即使这个新异常时父类方法声明中的任何一个异常的子类也不行
  • 不可以抛出 “被覆盖方法抛出异常” 的父类异常

例如:

  • 父类Animal方法fun()抛出两个异常:IndexOutOfBoundsException、IOException
  • 子类Cat覆盖方法fun()抛出异常最多两个,可以没有,同时子类抛出的异常,不能是父类抛出异常的父类,比如fun()不能抛出Exception(Exception是IndexOutOfBoundsException和IOException的父类)

可以这样理解:一个修理家电的人,他能够修理冰箱,电脑,洗衣机,电视机。 一个年轻人从他这里学的技术,就只能修理这些家电,或者更少。你不能要求他教出来的徒弟用从他这里学的技术去修理直升飞机。

1.2 throws

如果抛出当前抛出的异常不希望立即处理,则可以在方法声明处使用throws关键字,指出方法引发的异常。可以声明多种异常类型,以逗号分隔开即可。

  1. public void test throws xxxException1, xxxException2, xxxException3 { ... }

使用了throws的方法,被调用时就必须要求对其内的异常进行处理,同样,要么使用try-catch,要么继续使用throws往上抛,这种不断使用throws往上抛出异常直到被处理,就形成了一个所谓抽象的概念 “异常链”。

我们有时候在捕获一个异常后会抛出一个新的异常信息,并且希望将原始的异常信息也保存起来,这个时候也需要使用异常链。在Throwable及其子类中的构造器中都可以接受一个cause参数,该参数保存了原有的异常信息,通过getCause()就可以获取该原始异常信息。

  1. public class Test {
  2. public void f() throws MyException{
  3. try {
  4. FileReader reader = new FileReader("G:\\myfile\\struts.txt");
  5. Scanner in = new Scanner(reader);
  6. System.out.println(in.next());
  7. } catch (FileNotFoundException e) {
  8. //e 保存异常信息
  9. throw new MyException("文件没有找到--01", e);
  10. }
  11. }
  12. public void g() throws MyException{
  13. try {
  14. f();
  15. } catch (MyException e) {
  16. //e 保存异常信息
  17. throw new MyException("文件没有找到--02", e);
  18. }
  19. }
  20. public static void main(String[] args) {
  21. Test t = new Test();
  22. try {
  23. t.g();
  24. } catch (MyException e) {
  25. e.printStackTrace();
  26. }
  27. }
  28. }
  1. com.test9.MyException: 文件没有找到--02
  2. at com.test9.Test.g(Test.java:31)
  3. at com.test9.Test.main(Test.java:38)
  4. Caused by: com.test9.MyException: 文件没有找到--01
  5. at com.test9.Test.f(Test.java:22)
  6. at com.test9.Test.g(Test.java:28)
  7. ... 1 more
  8. Caused by: java.io.FileNotFoundException: G:\myfile\struts.txt (系统找不到指定的路径。)
  9. at java.io.FileInputStream.open(Native Method)
  10. at java.io.FileInputStream.<init>(FileInputStream.java:106)
  11. at java.io.FileInputStream.<init>(FileInputStream.java:66)
  12. at java.io.FileReader.<init>(FileReader.java:41)
  13. at com.test9.Test.f(Test.java:17)
  14. ... 2 more

如果在程序中,去掉e,也就是:throw new MyException("文件没有找到--02");  那么异常信息就保存不了,运行结果如下:

  1. com.test9.MyException: 文件没有找到--02
  2. at com.test9.Test.g(Test.java:31)
  3. at com.test9.Test.main(Test.java:38)

2、自定义异常

Java已经给我们提供了很多不同种类的异常,但是即使如此,也并不能预见所有的异常类型,特别是我们在业务上出现的错误。所以Java允许我们自定义异常,来表现程序中遇到的一些特殊问题。

我们自定义的异常类,主要还是用于标记业务逻辑的问题,避免与标准异常混淆。定义也很简单,只需要继承 Exception 即可:

  1. public class MyException extends Exception {
  2. public MyException(String msg){
  3. super(msg);
  4. }
  5. }

自定义异常中往往不写其他的方法,只需要重载使用的构造方法。当然,也可以不写,使用默认的构造方法即可。

自定义异常往往是通过 throw 进行抛出使用。

3、参考链接

时间: 2024-10-14 09:05:41

[02] 异常链和自定义异常的相关文章

[2]异常链、自定义异常

1.异常链 我们想要自己抛出异常,就要使用 throw 关键字. 显式地抛出异常通常写为: 1 throw new xxxException(); 异常抛出后,有两种处理方式: ● 立即处理,使用 try catch 捕获并处理 ● 稍后处理,丢给方法调用的上层处理,使用 throws 关键字 1.1throw 1.2throws 2.自定义异常 原文地址:https://www.cnblogs.com/fanyizhan/p/10018153.html

java异常丢失及异常链

异常丢失的情况: 先定义三个异常: public class ExceptionA extends Exception { public ExceptionA(String str) { super(); } } public class ExceptionB extends ExceptionA { public ExceptionB(String str) { super(str); } } public class ExceptionC extends ExceptionA { publi

java 第50节 Java中的异常链

2016-06-30 1 异常链 两个或多个不同的异常出现在同一个程序中,并且会发生嵌套抛出,我们称之为异常链. package com.java1995; /** * 异常链 * @author Administrator * */ public class ExceptionChainTest { public static void main(String[] args) { Calculator c=new Calculator(); try{ c.chufa(1, 0); }catch

java中的异常链

把捕获的异常包装成一个新的异常,在新的异常中添加对新的异常的引用,再把新异常抛出,就像是链式反应一样,这种就叫异常链. 代码实例: public static void main(String[] args){ ChainTest ct=new ChainTest();//创建chainTest实例 try{ ct.test2(); }catch(Exception e){ e.printStackTrace(); } } public void test1()throws DrunkExcep

第十二章 重新抛出异常与异常链

重新抛出异常: 如果你想把刚捕获的异常扔给上一级处理,尤其是在使用Exception捕获所有异常的时候,既然已经得到了对当前异常对象的引用,可以直接把它重新抛出.重新抛出会把异常抛给上一级环境中的异常处理程序,同一个try块的后续catch子句将被忽略,但finally块不会.此外,异常对象的所有信息都得以保持,所以高一级环境中捕获此异常的处理程序可以从这个异常对象中得到所有信息. 1 package 异常.Finally; 2 3 import java.io.IOException; 4 5

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

[0]README 0.1) 本文描述+源代码均 转自 core java volume 1, 旨在理解 java异常--捕获异常+再次抛出异常与异常链 的相关知识: [1]捕获异常相关 1.1)如果某个异常发生的时候没有再任何地方进行捕获, 那程序就会运行终止: 并在控制台上打印出异常信息 , 其中包括异常的类型堆栈的内容: 1.2)要想捕获一个异常, 必须设置 try/catch 语句块: 1.2.1)如果在try语句块中抛出了一个在 catch子句中声明的异常类, 那么 case1)程序将

Java提高:采用异常链传递异常

一.分析 异常需要封装,但是仅仅封装还是不够的,还需要传递异常.一个系统的友好型的标识,友好的界面功能是一方面,另一方面就是系统出现非预期的情况的处理方式了. 二.场景 比如我们的JEE项目一般都又三层:持久层.逻辑层.展现层,持久层负责与数据库交互,逻辑层负责业务逻辑的实现,展现层负责UI数据的处理. 又这样一个模块:用户第一次访问的时候,需要持久层从user.xml中读取数据,如果该文件不存在则提示用户创建之,那问题就来了:如果我们直接把持久层的异常FileNotFoundException

异常+异常链

异常: 在程序运行过程中发生的不正常事件 Java中所有异常都是Exception(父类) 传统处理程序中异常: System.exit(1);参数必须为非0数,结束/退出JVM(java虚拟机) System.err.println();控制台输出错误流,为红色字体. 异常处理机制: 为程序提供错误处理的能力 5个关键字: try 执行可能产生异常的代码 catch 捕获异常 finally 无论是否发生异常,代码都能执行 throw 声明异常,声明方法可能要抛出的各种异常 thorws 手动

如何来解决编程异常链呢

有的人在遇到异常链的时候不知道怎么解决,下面一起来看下出现异常链的时候如何解决: 在设计模式中有一个叫做责任链模式,该模式是将多个对象链接成一条链,客户端的请求沿着这条链传递直到被接收.处理.同样Java异常机制也提供了这样一条链:异常链. 我们知道每遇到一个异常信息,我们都需要进行try-catch,一个还好,如果出现多个异常呢?分类处理肯定会比较麻烦,那就一个Exception解决所有的异常吧.这样确实是可以,但是这样处理势必会导致后面的维护难度增加.最好的办法就是将这些异常信息封装,然后捕