Java中的异常

一、异常概述

1、什么是异常?

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

2、异常的抛出机制

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

3、如何对待异常

  • 对于程序出现的异常,一般有两种解决方法:一是遇到错误就终止程序的运行。另一种方法是程序员在编写程序时,就充分考虑到各种可能发生的异常和错误,极力预防和避免。实在无法避免的,要编写相应的代码进行异常的检测、以及异常的处理 ,保证代码的 健壮性。

二、JAVA中的异常处理

1、异常的体系结构

Throwable:Java程序执行过程中发生的异常事件对应的类的根父类.

具有Error和Exception两个子类

  • Error:Java虚拟机无法解决的严重问题。如: JVM系统内部错误、资源耗尽等严重情况。一般不编写针对性的代码进行处理。

  • Exception: 其它因编程错误或偶然的外在因素导致的一般性问题,需要使用针对性的代码进行处理,使程序继续运行。否则一旦发生异常,程序也会挂掉。例如:

    空指针访问
    读取不存在的文件
    网络连接中断
    数组角标越界

2.编译时异常和运行时异常

  • Java程序的执行分为编译时过程和运行时过程。有的错误只有在 运行时 才会发生。比如: 除数为0,数组下标越界等。
  • 编译时期异常 (即checked异常、受检异常): 在代码编译阶段,编译器就能明确 警示 当前代码 可能发生(不是一定发生) xx异常,并明确督促 程序员提前编写处理它的代码。如果程序员 没有编写 对应的异常处理代码,则编译器就会直接判定编译失败,从而不能生成字节码文件。通常,这类异常的发生不是由程序员的代码引起的,或者不是靠加简单判断就可以避免的,例如: FileNotFoundException (文件找不到异常)。
  • 运行时期异常 (即runtime异常、unchecked异常、非受检异常): 在代码编译阶段,编译器完全不做任何检查,无论该异常是否会发生,编译器都不给出任何提示。只有等代码运行起来并确实发生了xx异常,它才能被发现。通常,这类异常是由程序员的代码编写不当引起的,只要稍加判断,或者细心检查就可以避免。
    例如:
    ArrayIndexOutOfBoundsException 数组下标越界异常
    NullPointerException 空指针异常
    ClassCastException 类型转换异常
    NumberFormatException 数据格式异常
    InputMismatException 输入格式异常
    ArithmeticException 算术异常

三、两种常用的异常处理方式

方式一(抓抛模型):try-catch-finally

1.执行过程

  • 过程一、“抛 ”
    程序在执行的过程当中,一旦出现异常,就会在出现异常的代码处,生成对应异常类的对象,并将此对象抛出。一旦抛出,此程序就不执行其后的代码了。

  • 过程二、“抓”
    针对于过程1中抛出的异常对象,进行捕获处理。此捕获处理的过程,就称为抓。
    一旦将异常进行了处理,代码就可以继续执行。

2.基本结构

try{
… //可能产生异常的代码
}
catch(异常类型1 e){
… //当产生异常类型1异常时的处置措施
}
catch(异常类型1 e){
… //当产生异常类型2异常时的处置措施
}
finally{
… //无论是否发生异常都会执行的语句
}

3.使用细节

  • 将可能出现异常的代码声明在try语句中。一旦出现代码异常,就会自动生成一个异常类对象。

  • 针对于try中抛出的异常类的对象,使用之后的catch语句进行匹配。一旦匹配上,
    就进入catch语句块进行处理。
    一旦处理结束,代码就可继续向下执行。

  • 如果声明了多个catch结构,不同的异常类型在不存在子父类关系的情况下,谁声明在上面,谁声明在下面都可以。
    如果多个异常类型满足子父类的关系,则必须将子类声明在父类结构的上面。否则,报错。

  • catch中的异常处理方式
    ①.自己编写输出语句
    ②.printStackTrace():打印异常的详细信息
    ③.getMessage():获取发生异常的原因

  • try中声明的变量,出了try结构之后,就不可以进行调用了。

4.开发体会

  • 对于运行时异常:
    开发中,通常就不进行显式的处理了。
    一旦在程序执行中,出现了运行时异常,那么就根据异常的提示信息修改代码即可。

  • 对于编译时异常
    一定要处理,否则编译不通过。

5.finally的使用说明

  • finally的理解
    我们将一定要被执行的代码声明在finally结构中.即使try或catch中存在return finally结构中的代码也会在return之前被执行

  • 我们在开发中,有一些资源,比如:输入流,输出流,数据库的连接、Socket连接等资源,在使用完以后,必须显式的进行关闭操作,否则GC不会自动的回收这些资源。进而导致内存的泄露。
    为了保证这些资源在使用以后,不管是否出现了未被处理的异常,这些资源能被关闭,我们必须将这些操作声明在finally当中。

异常的处理方式二:throws

1.格式:

  • 在方法的声明处,使用“throws 异常类型1,异常类型2,…"

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

  • 从编译是否能通过的角度看,看成是给出了异常万一要是出现时候的解决方案。此方案就是,继续向上抛出(throws)。
  • 但是,此throws的方式,仅是将可能出现的异常抛给了此方法的调用者。此调用者仍然需要考虑如何处理相关异常.从这个角度来看,throws的方式不算是真正意义上处理了异常。

3.方法重写的要求(针对编译时异常)

  • 子类重写的方法抛出的异常类型可以与父类被重写的方法抛出的异常类型相同,或是父类被重写的方法抛出的异常类型的子类。

4.开发中如何选择异常处理的两种方式?

  • 如果程序代码中,涉及到资源的调用(流、数据库连接、网络连接等),则必须考虑使用try-catch-finally来处理保证不出现内存泄漏。
  • 如果父类被重写的方法没有throws异常类型,则子类重写的方法中如果出现异常,只能考虑使用try-catch-finally进行处理,不能throws。
  • 开发中,方法a中依次调用了方法b,c,d等方法,方法b,c,d之间是递进关系。此时,如果方法b,c,d中有异常我们通常选择使用throws,而方法a中通常选择使用try-catch-finally。

四、手动throw异常对象

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

  • 在实际开发中,如果出现不满足具体场景的代码问题,我们就有必要手动抛出一个指定类型的异常对象。
  • 在方法内部,满足指定条件的情况下,使用"throw 异常类的对象"的方式抛出。如果抛出的是RuntimeException则不必处理,但编译时异常必须做处理。

2.如何理解自动抛与手动抛异常?

  • 过程一:”抛“
    ”自动抛“:程序在执行的过程当中,一旦出现异常,就会在出现异常的代码处,生成对应异常类的对象,并将此对象抛出。一旦抛出,此程序就不执行其后的代码了。
    ”手动抛“:程序在执行的过程中,不满足指定条件下,我们主动的使用”throw +异常类对象“方式抛出异常对象。

  • 过程二、”抓“
    狭义上讲:try-catch的方式捕获异常,并处理。
    广义上讲:把抓理解为处理。

3.throw和throws的区别

  • throws属于异常的处理,在”抓“中,throw属于手动抛出一个异常,在”抛“中
  • 上游排污,下游治污。

五、自定义异常

1.如何自定义异常类?

①.继承于现有的异常体系,通常继承于RuntimeException、Exception
②.通常提供几个重载的构造器
③.提供一个全局常量,声明为:static final long serialVersionUID = …;

public class DefineException extends Exception{
    //自定义序列号,来唯一标识一个类
    static final long serialVersionUID = -3387516993229948L;
    public DefineException(){

    }
    public DefineException(String name){
        super(name);
    }
    public DefineException(String message , Throwable cause){
        super(message , cause);
    }
}

2.如何使用自定义异常类?

  • 在具体的代码中,满足指定条件的情况下,需要手动的使用"throw + 自定义异常类的对象"方式,将异常对象抛出。
  • 如果自定义异常类是非运行时异常,则必须考虑如何处理此异常类的对象。要么try-catch\throws

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

  • 我们需要通过异常名称,能直接判断出此异常出现的原因。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爪哇哇哇哇

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值