第09章:异常处理

1. 异常的概述、理解

1. 什么是异常?
指的是程序在执行过程中,出现的非正常情况,如果不处理最终会导致JVM的非正常停止。

2. 异常的抛出机制 ---> 万事万物皆对象
Java中把不同的异常用不同的类表示,一旦发生某种异常,就`创建该异常类型的对象`,并且抛出(throw)。
然后程序员可以捕获(catch)到这个异常对象,并处理;如果没有捕获(catch)这个异常对象,那么这个异常
对象将会导致程序终止。

3. 如何对待异常
> 态度1:一是遇到错误,不进行任何的处理,终止程序的运行。
> 态度2:如果之前的测试中出现了异常的情况,则修改代码,保证之后尽量不要出现同样的异常。
> 态度3:在编写程序时,就充分考虑到各种可能发生的异常和错误,极力预防和避免。实在无法避免的,
        要编写相应的代码进行异常的检测、以及`异常的处理`

2. 常见的异常(重点)

java.lang.Throwable
    |---java.lang.Error:错误
            > Java虚拟机无法解决的严重问题。如:JVM系统内部错误、资源耗尽等严重情况。
            > 一般不编写针对性的代码进行处理。
            > 常见的Error:StackOverFlowError,OutOfMemoryError

    |---java.lang.Exception:异常
            > 其它因编程错误或偶然的外在因素导致的一般性问题,需要使用针对性的代码进行处理,
               使程序继续运行。
            > 分类:编译时异常 、 运行时异常
            > 举例:
                    运行时异常:
                    NullPointerException
                    ArrayIndexOutOfBoundsException
                    ClassCastException
                    NumberFormatException
                    ArithmeticException
                    InputMismatchException
                    编译时异常:
                    ClassNotFoundException
                    FileNotFoundException
                    IOException

3. 异常的处理(重点)

3.1 try-catch-finally
  • try-catch的使用
1. 方式一(抓抛模型):

过程1:“抛”:Java程序的执行过程中如果出现异常,会生成一个对应异常类的对象,并将此对象抛出。


过程2:“抓”:针对于上一个过程中抛出的异常类的对象,进行的捕获(catch)行为。


2. 基本结构:
try{
    //可能出现异常的代码

}catch(异常类型1 e){
    //异常的处理方式
}catch(异常类型2 e){
    //异常的处理方式
}
...
finally{
    //一定会被执行的代码
}


3. 使用细节:
> finally是可选的。暂时先不考虑
> try中包裹的是可能出现异常的代码。如果在执行过程中,没有出现异常,则程序正常结束,不会考虑执行多个catch结构
  如果try中出现了异常,则会自动创建对应异常类的对象,并将此对象抛出。
        如果抛出的异常对象匹配某个具体的catch结构,则进入相应的catch中进行处理。一旦执行结果,就跳出当前结构,继续执行其后的代码
        如果没有匹配到相应的catch结构,则相当于没有捕获异常,会导致程序的终止。
> 如果多个catch中的异常类型有子父类关系,则必须将子类异常的捕获声明在父类异常捕获的上面。
> try中声明的变量,在出了try的一对{}之后,就失效了。
> catch中异常处理的方式:
        方式1:自己自定义输出语句
        方式2:调用异常类的现有方法:方法1:调用printStackTrace(),用于打印异常出现的堆栈信息。(推荐)
                               方法2:调用getMessage(),返回一个异常的字符串信息


4. 开发体会:
   > 对于运行时异常:实际开发中,我们通常都不再处理运行时异常。

   > 对于编译时异常:实际开发中,我们是必须要提前给出异常方案。否则,编译不通过。
  • finally的使用
1. finally的理解
> 将一定会被执行的代码声明在finally中
> finally结构是可选的。
> 不管try、catch中是否存在未被处理的异常,不管try、catch是否执行了return语句;finally是一定要被执行的结构。

2. 什么样的代码我们一定要声明在finally中呢?
> 开发中会涉及到相关的资源(流、数据库连接)的关闭的问题,如果相关的资源没有及时关闭,会出现内存泄漏。
  为了避免出现内存泄漏,我们必须将其关闭操作声明在finally中,确保在出现异常的情况下,
  此关闭操作也一定会被执行。
3. 面试题
final 、 finally 、finalize 的区别
3.2 throws
1. 格式:
在方法的声明处,使用"throws 异常类型1,异常类型2,..."

2. 举例:
public void method1() throws FileNotFoundException, IOException{}

3. 是否真正处理了异常?

> 从是否能通过编译的角度来说:使用throws的方法声明了可能出现的异常的类型,使得编译能通过。
> 从是否真正意义上解决了可能抛出的异常对象:并没有。只是将可能出现的异常对象继续向上抛出。
                                   只有使用try-catch-finally的方式才是真正意义上处理了异常。


4. 方法的重写的要求:

针对于编译时异常:
子类重写父类中的方法,要求子类重写的方法抛出的异常类型不大于父类被重写方法抛出的异常类型。
比如:父类被重写的方法throws 异常类型1,子类可以throws异常类型1或异常类型1的子类。

针对于运行时异常:没有这样的要求。  ----> 开发中,针对于运行时异常,也不会进行try-catch或throws的处理。
  • 如何选择两种处理方式?
开发中,如何选择异常处理的两种方式?(重要、经验之谈)

> 情况1:如果程序中使用了相关的资源,为了确保这些资源在出现异常的情况仍然能被执行关闭操作。
        建议使用:try-catch-finally。将资源的关闭操作声明在finally中。

> 情况2:如果父类中被重写的方法没有使用throws的结构,则子类重写父类的方法中如果出现编译时异常,只能
        使用try-catch-finally的方式进行处理。

> 情况3:如果在方法1中依次调用了方法2,3,4,而且此时的方法2,3,4是递进调用的关系。则通常方法2,3,4中
        出现异常的情况下,选择使用throws的方式进行异常的处理,在方法1中使用try-catch-finally进行处理。

4. 手动抛出异常的对象(熟悉)

1. 为什么需要手动抛出异常?

在实际开发中,为了满足实际问题的需要,必要时需要手动的throw一个异常类的对象。
比如:要求分子、分母都不能为负数。如果出现负数了就报错。如何体现报错呢?手动抛出异常类的对象。
比如:给学生的id赋值,要求此id不能为负数。如果赋值为负数,就报错。如何体现报错呢?手动抛出异常类的对象。


2. 如何理解"自动 vs 手动"抛出异常对象?

过程1:“抛”:Java程序的执行过程中如果出现异常,会生成一个对应异常类的对象,并将此对象抛出。
    情况1:自动抛出(throw)

    情况2:手动抛出(throw):在方法体内使用


过程2:“抓”:针对于上一个过程中抛出的异常类的对象,进行的捕获(catch)行为。
    广义上"抓"理解为异常处理的方式:
        > 方式1:try-catch-finally
        > 方式2:throws:使用在方法的声明处

类比:上游排污、下游治污。

3. 如何实现手动抛出异常?
在方法体的内部,满足某个条件的情况下,使用“throw + 异常类的对象”。


4. 注意点:throw后的代码不能被执行,编译不通过。

[面试题] 区分throw和throws

5. 如何自定义异常类(熟悉)

1. 如何自定义异常类? (参照着Exception、RuntimeException进行设计即可)
① 继承于现有的异常体系结构中的某一个类。比如继承于RuntimeException、Exception
② 提供几个重载的构造器
③ 提供一个全局常量serialVersionUID,用于唯一的标识当前类


2. 如何使用自定义异常类?
在满足相应情况的条件下,方法体内使用"throw + 自定义异常类的对象"的方式使用。


3. 为什么需要自定义异常类?

我们在开发中,针对于出现的异常,比较关心的是异常的名称。通过异常名,就可以直接定位出现的异常的问题。
所以,我们在开发中,具体到项目的具体要求时,我们都可以抛出自己定义的异常类型的对象。

五个关键字:

try-catch-finally

throws

throw

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值