Java基础——异常

异常:是在运行时期发生的不正常情况
在Java中用类的形式对不正常情况进行了描述和封装对象
描述不正常的情况的类称为异常类,以前将正常流程代码和问题处理代码相结合
现在讲正常流程代码和问题代码分离,提高阅读性,其实异常就是Java通过面向对象的思想将问题封装成了对象
用异常类对其进行描述,不同的问题用不同的类进行具体的描述,比如角标越界、空指针等等
问题很多,意味着描述的类也很多,将其共性进行向上抽取,形成了异常体系
最终问题(不正常情况)就分成了两大类:
Throwable:无论是error还是异常,都是问题,问题发生就可以抛出
该体系的特点就在于Throwable及其所有的子类都具有可抛性,子类的后缀名都是用其父类名作为后缀,阅读性很强
被throw throws关键字所操作的类和对象都具备可抛性
|—1、一般不可处理的:Error
特点:是由JVM抛出的严重性的问题,这种问题一般不针对性处理,直接修改程序
|—2、可以处理的:Exception

对于Java没有定义过的异常,可以按照Java异常的思想面向对象实行自定义异常
注意:如果让一个类称为异常类,必须要继承异常体系

异常的分类:
1、编译时被检测异常:只要是Exception和子类都是,除了特殊子类RuntimeException体系
这种问题一旦出像,希望编译时就进行检测,让这种问题有对应的处理方式,这样的问题都可以针对性的处理
2、编译时不检测异常(运行时异常):就是Exception中的RuntimeException和其子类
这种问题的发生,无法让功能继续,运算无法进行,更多是因为调用者的原因导致的而引发了内部状态改变导致的
这种问题一般不处理,直接编译通过,在运行时,让调用者调用时的程序强制停止,让调用者对代码进行修正
所以自定义异常时,要么继承Exception,要么继承RuntimeException

throw和throws的区别:
1、throws使用在函数上,throw使用在函数内
2、throws抛出的是异常类,可以抛出多个,用逗号隔开,throw抛出的是异常对象

举例说明

class FuShuIndexException extends Exception //自定义异常
{
    FuShuIndexException()
    {}
    FuShuIndexException(String msg)
    {
        super(msg);//继承父类的方法
    }
}
class Demo
{
    public int method(int[] arr,int index) throws FuShuIndexException //方法需要声明
    {
        if(arr==null)
        {
            throw new NullPointerException("数组的引用不能为空!");//抛异常

        }
        if(index>=arr.length)
        {
            throw new ArrayIndexOutOfBoundsException("数组的角标越界!"+index);
        }

        if (index<0)
        {
            throw new FuShuIndexException("角标变成负数了");
        }
        return arr[index];
    }
}
class  ExceptionDemo
{
    public static void main(String[] args) throws FuShuIndexException  //调用可能出现异常方法的函数需要声明
    {
        int[] arr=new int[3];
        Demo d=new Demo();
        int num=d.method(null,-30);
        System.out.println("num="+num);
        System.out.println("Hello World!");
    }
}

异常的处理方式
异常处理的捕捉形式:
这是可以对异常进行针对性处理的方式
具体格式是:
try
{
//需要被检测异常的代码
}
catch(异常类 变量)//该变量用于接收发生的异常对象
{
//处理异常的代码
}
finally
{
//一定会被执行的代码
}

异常处理原则:
1、函数内部如果抛出需要检测的异常,那么函数上必须要声明
否则必须在函数内用trycatch捕捉,否则编译失败
2、如果调用了声明异常的函数,要么trycatch要么throws,否则编译失败
3、什么时候catch,什么时候throws呢?
功能内部可以解决,用catch
解决不了,用throws告诉调用者,由调用者解决
4、一个功能如果抛出了多个异常,那么调用时,必须有对应多个catch进行针对性的处理,内部有几个
需要检测的异常,就抛出几个,就catch几个。

异常的注意事项:
1、子类在覆盖父类方法时,父类的方法如果抛出了异常
那么子类的方法只能抛出父类的异常或者该异常的子类
2、如果父类抛出多个异常,那么子类只能抛出父类异常的子集
简单的说:子类覆盖父类只能抛出父类的异常或者子类或者子集
注意:如果父类的方法没有抛出异常,那么子类覆盖时绝对不能抛,就只能try

代码说明:

class FuShuIndexException extends Exception //自定义异常
{
    FuShuIndexException()
    {}
    FuShuIndexException(String msg)
    {
        super(msg);//继承父类的方法
    }
}
class Demo
{
    public int method(int[] arr,int index) throws FuShuIndexException
    {

        if (index<0)
            throw new FuShuIndexException("角标变成负数了");
        return arr[index];
    }
}
class  ExceptionDemo1
{
    public static void main(String[] args) 
    {
        int[] arr=new int[3];
        Demo d=new Demo();
        try
        {
            int num=d.method(arr,-30);
            System.out.println("num="+num);
        }
        catch (FuShuIndexException e)
        {
            System.out.println("message:"+e.getMessage());
            e.printStackTrace();//jvm默认的异常处理机制就是调用异常对象的这个方法
            System.out.println("负数角标异常!!!");
        }

        System.out.println("Over");
    }
}

try finally异常无法直接cathc处理,但是资源要关闭
例:
void show() throws Exception
{
try
{
//开启资源
throw new Exception();
}
finally
{
//关闭资源
}
}
代码:

class Demo
{
    public int show(int index) throws ArrayIndexOutOfBoundsException
    {
        if(index<0)
            throw new ArrayIndexOutOfBoundsException("越界了");
        int [] arr=new int[3];
        return arr[index];

    }

}
class ExceptionDemo5 
{
    public static void main(String[] args) 
    {
        Demo d=new Demo();
        try
        {
            int num=d.show(-3);
            System.out.println("num="+num);
        }
        catch (ArrayIndexOutOfBoundsException e)
        {
            System.out.println(e.toString());
            //return; //有这个语句的时候System.out.println("over");不执行,但是finally里的还是执行
            //System.exit(0);//退出jvm,这样子的话fianlly里的也不执行
        }

        finally//通常用于关闭(释放)资源
        {
            System.out.println("finally");
        }

        System.out.println("over"); 
    }
}

异常应用方式举例

场景:

老师用电脑上课:
问题领域中涉及两个对象:老师、电脑
分析其中的问题:
比如电脑蓝屏、冒烟

class LanPingException extends Exception
{
    LanPingException(String msg)
    {
        super(msg);
    }
}
class MaoYanException extends Exception
{
    MaoYanException(String msg)
    {
        super(msg);
    }
}
class NoPlanException extends Exception
{
    NoPlanException(String msg)
    {
        super(msg);
    }
}
class Computer
{
    private int state=2;
    public void run() throws LanPingException,MaoYanException 
    {
        if(state==1)
            throw new LanPingException("电脑蓝屏了");
        if(state==2)
            throw new MaoYanException("电脑冒烟");

        System.out.println("电脑运行");
    }
    public void reset()
    {
        state=0;
        System.out.println("电脑重启");
    }
}
class Teacher
{
    private String name;
    private Computer comp;
    Teacher(String name)
    {
        this.name=name;
        comp=new Computer();
    }
    public void prelect() throws NoPlanException
    {
        try
        {
            comp.run();
            System.out.println(name+"讲课");
        }
        catch (LanPingException e)
        {
            System.out.println(e.toString());
            comp.reset();
            prelect();
        }
        catch (MaoYanException e)
        {
            System.out.println(e.toString());
            test();
            //可以对电脑进行维修
    //      throw e;
            throw new NoPlanException("可是进度无法完成,原因是:"+e.getMessage());
        }
    }
    public void test()
    {
        System.out.println("大家练习");
    }
}
class  ExceptionTest
{
    public static void main(String[] args) 
    {
        Teacher t=new Teacher("老师");
        try
        {
            t.prelect();
        }
        catch (NoPlanException e)
        {
            System.out.println(e.toString()+".......");
            System.out.println("换人");
        }

    }
}

try–catch–finally执行顺序(涉及到return)

情况1:try{}
catch(){}
finally{}
return;

// 显然程序按顺序执行。

情况2:
try{ return; }
catch(){}
finally{}
return;

// 程序执行try块中return之前(包括return语句中的表达式运算)代码;
// 再执行finally块,最后执行try中return;
// finally块之后的语句return,因为程序在try中已经return所以不再执行。

情况3:
try{ }
catch(){return;}
finally{}
return;

// 程序先执行try,如果遇到异常执行catch块,
// 有异常:则执行catch中return之前(包括return语句中的表达式运算)代码,再执行finally语句中全部代码,
// 最后执行catch块中return. finally之后的代码不再执行。
// 无异常:执行完try再finally再return.

情况4:
try{ return; }
catch(){}
finally{return;}

// 程序执行try块中return之前(包括return语句中的表达式运算)代码;
// 再执行finally块,因为finally块中有return所以提前退出。

情况5:
try{}
catch(){return;}
finally{return;}
// 程序执行catch块中return之前(包括return语句中的表达式运算)代码;
// 再执行finally块,因为finally块中有return所以提前退出。

情况6:
try{ return;}
catch(){return;}
finally{return;}
// 程序执行try块中return之前(包括return语句中的表达式运算)代码;
// 有异常:执行catch块中return之前(包括return语句中的表达式运算)代码;
// 则再执行finally块,因为finally块中有return所以提前退出。
// 无异常:则再执行finally块,因为finally块中有return所以提前退出。

代码演示:
这里写图片描述

分析:
在执行try代码块中,发生异常,跳到catch代码块处理,在执行return语句时,要返回的结果已经准备好了,
就在此时,程序转到finally执行了。在转去之前,catch代码中先把要返回的结果存放到栈保存,执行完finally之后,
再从中取出返回结果,因此,即使finally中对变量str进行了改变,但是不会影响返回结果。

结论:
1、不管有木有出现异常,finally块中代码都会执行;
2、当try和catch中有return时,finally仍然会执行;
3、finally是在return后面的表达式运算后执行的(此时并没有返回运算后的值,而是先把要返回的值保存起来,
管finally中的代码怎么样,返回的值都不会改变,仍然是之前保存的值),所以函数返回值是在finally执行前确定的;
4、finally中最好不要包含return,否则程序会提前退出,返回值不是try或catch中保存的返回值。
5、如果try、catch块中存在System.exit(0)语句,那么就不会执行finally块中的代码,
因为System.exit(0)会终止当前运行的Java虚拟机,程序会在虚拟机终止前结束执行。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值