Exception异常

胡泽宇 2020年02月18日 44次浏览

异常

异常处理的流程

try{
    //正常的处理逻辑,可能会出现异常
}
catch{ //catch块可以出现0~N次
    //处理错误
}
finally{
    //用于回收资源 
    //Java会包装无论是否出现异常,finally块总会执行
}
//将正常的业务处理代码,放在try块里面
//将对异常的处理逻辑,放在catch块里面

执行try时如果遇到了异常,Java会自动将异常封装成Exception对象。
该对象会提交给Java运行时环境
这个过程就叫 throw "抛出"

异常处理流程每次只进入一个catch块。
处理异常时,要先处理子类异常,再处理父类异常。
如果有try块,catch块和finally块至少出现一次。
实例:
0

异常的体系

1

Error:代表非常严重的,不可恢复的错误,因此程序不要处理Error。
Exception:代表程序中可恢复的错误,一般会要求程序处理Exception。

Java7提供了多异常捕捉

//下标超界,数字格式化错误都可以被捕捉
catch(IndexOutOfBoundsException | NumberFormatException e){
    System.out.println(e);
}

注意点:

  1. catch块中使用竖线 | 隔开多个异常类。
  2. 多异常步骤时,该异常变量是有隐式的final修饰的。

final、finally、finalize的区别

final: 修饰符。用于修饰变量、方法、类。
finally: finally块。
finalize:只是Object的一个方法。所有对象会被GC之前,系统会自动调用改对象的finalize方法,程序永远不会调用finalize方法。只是JVM调用。

面试题: 到底输出多少

2

为啥会输出7? 因为在try块中快结束的时候(return)的时候
检查该try块下面是否有finally块,如果有,会执行finally块,然后才来返回
因为前面已经到了return ++a
所以a等于6,但是到了finally块中又有一个return ++a
所以就在finally块中return回去了。

从上面可以看出:
finally块总会执行,连return都阻止不了它的执行。

异常处理的嵌套

一般来说,可能在catch块或finally块中再次使用
try...catch来处理异常--->这就叫异常嵌套。

Java7的自动关闭资源的try语句

try(
    //声明、并创建需要自动关闭的资源。
){
    //try语句块
}

3个注意点:
自动关闭的资源必须要实现Closeable或AutoCloseable接口。
这两个接口是用于保证该资源是可自动关闭。
Closeable是AutoCloseable的子接口。
自动关闭资源的try语句自带隐式finally,因此它可以既没有catch块,也没有finally块

普通try语句不能独立存在,自动关闭资源的try可以独立存在

实例:
3

异常的常用方法

Exception继承Throwable
所有异常都是Exception的子类

String getMessage()   获取异常的信息
String getStackTrace()   获取异常的跟踪栈(堆栈)信息
void printStackTrace()  打印异常的跟踪栈(堆栈)信息

堆栈信息实例:

  • 首先创建了三个类 A/B/C
    A
    B
    C
  • 运行A类里的main方法报错
    报错

技巧:通过跟踪栈调试错误时,应该从下往上,找到一个自己写的类,进行调试。

checked异常和runtime异常

  • runtime异常:所有RuntimeException及其子类的实例,都是runtime异常。(想处理runtime异常就处理,不想处理就不处理(编译不会报错))
    • Error: 代表了严重,不可恢复的错误,因此不强制开发者处理。
    • 但在程序运行时遇到未捕获的runtime异常或Error,程序还是会中止。
  • checked异常:不是RuntimeException,就是checked异常(要么显式使用try...catch,要么声明抛出(编译报错))。

throws声明抛出异常

在方法签名上使用

throws 异常类1,异常类2,异常类3,...
throws可以一次声明多个异常

throw抛出异常

在某些时候,程序中出现了一种与业务不符合的情况,主动抛出异常。
throw 异常实例;
//throw是一个独立使用语句,用于抛出一个异常。
  • 如果方法中throw了一个异常,表面这段代码可能抛出异常。
    • 如果该异常时checked异常,要么声明抛出,要么try...catch,否则编译不通过(绝大部分都是声明抛出)。
    • 如果该异常是runtime异常,编译总可以通过,因此不用管它。

实例:
1
2
3

自定义异常

自定义异常,要继承Exception或RuntimeException
    如果要定义runtime异常,就继承RuntimeException
    如果要定义checked异常,就继承Exception

实例 创建一个checked自定义异常:
1
2
3

catch和throw结合使用

在某些情况下,catch块捕获了异常,
程序也对该异常进行了部分处理,但依然不能处理完成,
此时就需要在catch块中再次抛出新的异常对象。

实例 将checked异常捕获处理成runtime异常:
1
2
没有进行处理的checked异常,过不了编译
3

面试题:

熟悉的5个runtime异常:

  • NullPointerException 空指针异常
  • IndexOutOfBoundsException 索引越界异常
  • ArithmeticException 算数异常
  • NumberFormateException 数字格式化异常
  • IllegalArgumentException 非法参数异常

throws、throw、throwable的区别:

  • throws
    • 声明抛出异常,只能在方法签名上使用。
    • 声明抛出异常,代表该方法暂时不处理这些异常,这些异常交给该方法调用者处理。
    • throws可声明抛出多个异常类。
  • throw
    • 抛出异常实例。是一条独立的执行性语句。
    • throw可放在方法体、构造器、初始化块中使用。
    • throw只能抛出一个异常对象。
  • throwable
    • Throwable是Exception和Error共同的父类。