0%

异常

异常指的程序或者电脑发生不正常的现象所引发程序无法执行和崩溃,例如:文件找不到,网络连接失败等待。

在 java 中,异常都是对象,是 Throwable 的子类,Throwable 的子类都描述着不同的异常和错误。如下图,Java 异常类层次结构图
image

一 异常的架构体系

1.1Throwable(超类)

所有异常的祖先,用两个重要的子类:Exception(异常),Error(错误),两者各自也包含了大量的子类。

1.1.1 Error(错误)

是程序无法处理的错误,意思是运行程序中较为严重的问题,表示 jvm 出现了问题,大多数与代码编写者的操作无关,例如 virtual machineError ,当 JVM 不再有继续执行操作所需的内存资源时,将出现 OutOfMemoryError。这些异常发生时,Java虚拟机(JVM)一般会选择线程终止

1.1.2 Exception(异常)

是程序本身可以处理的异常。Exception 有一重要的子类, RuntimeException。RuntimeException 类及其子类表示“JVM 常用操作”引发的错误。例如,若试图使用空值对象引用、除数为零或数组越界,则分别引发运行时异常。

1.1.3 可查异常 (checked exceptions)

编译器要求必须处置的异常

非运行时异常又叫做编译异常,除了 RuntimeException 及它的子类以外的 Excetion 的子类(都是可查异常),如果不处理是不会编译通过

1.1.4 不可查异常(unchecked exceptions )

编译器不要求强制处理的异常,包括运行时异常(RuntimeException 以及它的子类 还有错误)

其中运行时异常),程序可以选择捕获处理也可以不处理。因为编译器是不会检查它,没有两种异常处理方式也能通过编译。

二 处理异常机制

一共有两种处理异常机制,分别是抛出异常,捕捉异常

2.1 捕捉异常

关键字 try catch finally

1. try-catch形式

1
2
3
4
5
6
7
8
try{
//可能会发生的异常代码
//监控区域
}catch(Kind1 e){
//捕获并处置try抛出的异常类型kind1
}catch(Kind2 e){
//捕获并处置try抛出的异常类型kind2
}

当try中(监控区域出现异常)则抛出监控区域之外,Java 会试图寻找匹配的 catch 字句,以捕获异常,若有匹配则执行 catch 中的语句,try-catch 语句结束
注意:
catch 语句中的异常不一定匹配对应所抛出的异常,可以是对应的异常类,也可以对应的异常类的子类

一旦某个 catch 捕获到匹配的异常类型,就进入异常处理,并且其他的 catch 语句将不会被匹配和捕获异常的机会

对于多个异常,应尽量及将低层的类(子类)捕获的异常类的 catch 语句防止前面,相对高层的异常类放在后面,不然高层的父类放前面可能会屏蔽子类的。

2. finally语句

1
2
3
4
5
6
7
8
9
try{

}catch(Kind kind1){

}catch(Kind kind2){

}finally{
//无论发生什么异常,都将执行该语句块
}

注意:
在 finally 语句中使用 return 语句以及抛出新的异常,会导致原有抛出的异常丢失。
当 try 块或者 catch 语句块遇到 return 语句时,finally 语句块将在方法返回之前执行,如果 finally 同时也有 return 语句,try 和 catch 语句的 return 将被覆盖。

3. 执行顺序
  • try 没有捕获异常时
    • try 语句被逐一执行并且在执行完 try 之后的 catch 忽略, finally 和之后语句继续执行
  • 当try捕获到异常,catch语句块里没有处理此异常的情况:
    • 当try语句块里的某条语句出现异常时,而没有处理此异常的catch语句块时,此异常将会抛给JVM处理,finally语句块里的语句还是会被执行,但finally语句块后的语句不会被执行
  • 当try捕获到异常,catch语句块里有处理此异常的情况:
    • 当执行某一条语句出现异常时,程序将逐一匹配 catch ,找到与之对应的处理程序,其他的catch语句块将不会被执行,而try语句块中,出现异常之后的语句也不会被执行,catch语句块执行完后,执行finally语句块里的语句,最后执行finally语句块后的语句;

2.2 抛出异常

  1. throws 抛出异常

    1
    2
    3
    public(...) void methodname throws Exception1,Exception2,,,{
    //.......
    }

    如果一个方法可能会出现异常,但没有能力处理这种异常,可以在方法声明出用 throws 语句来声明抛出的异常。并且也可以在方法体内写 throw 语句

    throws 语句用在方法定义时要抛出的类型。Exception 则是所有异常。多个类型用逗号分隔。
    此时抛出的异常,将交给调用该方法的方法处理。

注意:

  1. 如果时不可查异常,即Error,RuntimeException以及子类,那么可以不用 throws 声明要抛出的异常,由系统自动抛出。

  2. 如果时可查异常。即比如IOException ,就要么使用 try catch 来捕获,要么使用 throws 字句声明将他抛出。

  3. 仅仅抛出的异常,该方法的调用者必须处理或者重新抛出

  4. 覆盖一个方法,不能声明与覆盖方法不同的异常,必须是覆盖方法声明的异常同类或子类。

  5. 使用 throw 抛出异常

throw 是在方法体当中,抛出 Throwable 类型异常,程序会在 throw 语句之后立即结束程序

1
throw new Exception();

注意:

  1. 抛出的异常只能是 Throwable 类或者子类
  2. 如果抛出了检查异常,则还要在方法头部声明方法可能抛出的异常类型。该方法调用者也必须检查处理抛出的异常。

三 Throwable 常用的方法

catch关键字后面括号中的Exception类型的参数e。Exception就是try代码块传递给catch代码块的变量类型,e就是变量名。catch代码块中语句”e.getMessage();”用于输出错误性质。通常异常处理常用3个函数来获取异常的有关信息:

  1. getCause():
    • 返回抛出异常的原因。如果 cause 不存在或未知,则返回 null。
  2. getMeage():
    • 返回异常的消息信息。
  3. printStackTrace():
    • 对象的堆栈跟踪输出至错误输出流,作为字段 System.err 的值。

      自定义异常

      只需要基础 Exception 类即可
      步骤
  4. 创建自定义异常类
  5. 在方法中通过 throw 关键字抛出异常对象
  6. 如果在当前抛出异常的方法中处理异常,可以使用try-catch语句捕获并处理;否则在方法的声明处通过throws关键字指明要抛出给方法调用者的异常,继续进行下一步操作。
  7. 在出现异常方法的调用者中捕获并处理异常。

本文标题:异常

文章作者:志者

发布时间:2019年08月16日 - 15:43:00

最后更新:2019年08月28日 - 17:33:45

原始链接:http://witman1999.github.io/异常.html

许可协议: 署名-非商业性使用-相同方式共享 4.0 国际 转载请保留原文链接及作者。

-------------本文结束感谢您的阅读-------------
copy