黑马程序员--Java基础--java中的异常

——Java培训、Android培训、iOS培训、.Net培训、期待与您交流! ——-

异常

什么是异常呢?
异常就是不正常的,程序在运行时出现的不只正常情况。归根究底就是程序出问题了。是不过是把这个问题进行描述,并封装成对象。既然是问题,就会有产生问题的原因,产生问题的名称等一些问题的描述信息。而Java的面向对象的思想就是将这些问题进行了封装,方便于操作问题和处理问题。

异常体系:java.lang.Throwable这是所有异常的超类。
Throwable(可抛出的):
|–Error:错误,一般情况下不编写针对性的代码进行处理。通常是由居民发出的,需要对程序进行修正。
|–Exception:异常,可以有针对性的处理方式。

在这个体系中,所有的类和对象都具备可抛性。什么是可抛性呢?就是可以被throws和throw这两个关键字所操作。

那么在实际开发中,怎样使用异常呢?
当我们所写的一些功能在运行的过程中可能会出现一些问题,这时我们就应该在定义这个功能时标识出来,这样调用者就会在使用这个功能时预先给出处理方式。

那么我们是如何标识呢?其实就是通过throws关键字来完成的,格式:throws 异常类名,异常类名…我们这样标识后,后者在调用时,就必须要进行处理,否则编译失败。

那么问题又来了,我们在调用时就必须要进行处理,那么怎样处理呢?
处理的方式:1.捕捉到并进行处理。2.不捕捉,直接抛出。
第一种处理方式用代码怎样体现的呢?要知道这种处理方式,是有针对性的语句进行处理的。
try{
需要被检测的代码(既有问题的代码);
}
Catch(异常类 变量名){
具体的针对系的异常处理代码;
}
finally{
一定会执行到的代码;
}
此外try catch finally还有另外两种组合方式:
1.try finally。用于如果捕捉到异常,但是不进行处理,但是资源一定要被关闭的情况。
记住:finally有很大的用处,主要用于关闭资源,无论是否发生异常,资源都必须被关闭。
2.try catch。

代码演示:

class ExceptionDemo 
{
    public static void main(String[] args) 
    {
        int[] arr = new int[3];//创建一个长度为3的数组。

        try{
            System.out.println(arr[3]);//编译时没有错误,但运行时会报错。说明这是有问题的代码。
        }
        catch(Exception e){
            System.out.println("异常信息:"+e.getMessage());//获取异常信息的代码。
            System.out.println("toString:"+e.toString());//获取异常名和异常信息的代码。
            e.printStackTrace();//打印异常在堆栈中的信息,包括:异常名+异常信息+异常位置。
        }
        finally{
            System.out.println("我是一定会执行到的代码哦!");
        }
    }
}

打印的结果如下图:

这里写图片描述

重点:

异常处理的原则:
一个功能抛出几个异常,在调用该功能时,如果进行try处理,就需要与之对应的catch处理代码块,这样有针对性的处理,就是抛出几个就处理几个。
特殊情况:try对应多个catch时,如果有父类的catch语句块,一定要放在下面。
throws和throw的区别:
1.throw用于抛出异常对象, 后面跟的是异常对象,用在函数内。
2.throws用于抛出异常类,后面跟的是异常类名,可以跟多个,用逗号隔开,用在函数上。
通常情况下,函数内容如果有throw抛出异常对象,但是并没有进行处理,那么在函数上则一定要用throws进行声明异常类,否则编译失败。

异常分为两种:
1.编译时期的异常。只要是Exception及其子类都是编译时被检测的异常。
2.运行时期的异常。在Exception的子类中有一个特殊的子类:RuntimeException以及其子类都是运行异常,也就是说这个异常是在编译时期不被检测到的。

编译时异常和运行时异常的区别:
1.编译时异常在函数内被抛出,函数必须要声明异常类,否则编译失败。
2.声明的原因是告诉调用者该异常是需要被处理的。
3.运行时异常如果在函数内被抛出,在函数是上可以不需要声明异常类的。
不声明的原因:不需要调用者进行处理的。运行时异常发生时,已经无法在让程序继续运行了,所以不让调用者处理,而是直接让程序停掉,让调用者对代码进行修改。

在定义异常时,什么时候需要try,什么时候定义throws呢?
1.功能内部如果出现异常,如果在内部可以处理,则用try。
2.如果在内部不能处理,则就需要将该异常抛出,既是在函数上进行声明,则用throws。

重点:自定义异常类。
什么是自定义异常类呢?
如果在Java中出现的问题并没有进行定义时,这时就需要我们用Java中建立异常的思想,将这些特殊的问题进行封装成对象。这个异常就是自定义异常。

那么怎样自定义异常类呢?
1.定义一个子类并继承Exception或者RuntimeException,让该子类具备可抛性。
2.通过throws或者throw进行操作。
在处理异常时,我们要灵活运用异常转换思想,该异常如果处理不了,可以将该异常转换成一个可以被调用者处理的异常,然后进行抛出。

异常在继承中的新特点:
1.当子类覆盖父类的方发时,如果父类的方法抛出了异常,那么子类的方法要么不抛出异常,要么抛出该父类的异常或者该异常的子类,不能抛其他异常。
2.如果父类抛出了多个异常,那么子类在覆盖时,只能抛出父类的异常的子集。
3.如果父类中的方法并没有抛出异常,那么子类是不可以抛出异常的,如果子类覆盖的方法中出现了异常,只能try不能throws。
4.如果这个异常子类无法处理,已经影响了子类方法的具体运算,这时可以在子类方法中,用throw的方法抛出RuntimeException异常或者其子类,这样子类方法上是不需要进行声明的。
异常要尽量避免,如果避免不了,就要预先给出处理方法,就好像灭火器,备用药一样。
代码演示:

/*
    自定义异常代码演示。需求:除数不能为负数的自定义异常。
*/
class Test 
{
    public static void main(String[] args) 
    {
        //用try来捕捉除数为负数的异常。
        try{
            new Demo().div(4,-1);//创建一个具有除法功能的对象,并调用除法运算方法。

        }
        catch(FuShuException e){//对try捕捉到的异常进行具体的处理。
            System.out.println(e.toString());//打印异常的信息。
            System.out.println("错误的负数是:"+e.getValue());//打印除数为负数的具体值。
        }
    }
}
class Demo//自定义的具有除法运算功能的类。
{
    //除法运算的方法。
    public void div(int a,int b)throws FuShuException{
        if(b<0)//判断除数是否为负数。
            throw new FuShuException("错误:除数为负数。",b);//抛出除数为负数的异常对象。
        System.out.println("结果为:"+(a/b));//打印这两个数相除的结果。
    }
}
class FuShuException extends Exception//这是自定义的除数为负数的异常类,继承了Exception类。
{
    private int value;//用来记录错误的负数。
    FuShuException(){}//空参数的构造函数。
    //具有错误信息的构造函数。
    FuShuException(String msg,int value){
        super(msg);
        this.value = value;
    }
    //获取负数的方法。
    public int getValue(){
        return value;
    }

}

总结:异常分为两种。
1.编译时的异常。Exception。此异常及其子类在编译时都会被检测到。如果在函数内被抛出,那么在函数上必须要声明,否则编译失败。
2.运行时的异常。RuntimeException。此异常及其子类都是运行时异常,在编译时是不被检测到的。如果在函数内被抛出,那么在函数上是可以不声明的。因为只要是运行时异常,那么该程序就没必要在运行下去了,此时该程序就必须停止运行。
最重要的是自定义异常。怎样让一个类成为自定义异常呢?只要该类继承这两个异常类就可以了。

——Java培训、Android培训、iOS培训、.Net培训、期待与您交流! ——-

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值