异常:在运行时,发生不正常的情况


在java中用类的形式对不正常情况进行了描述和封装对象


描述不正常情况的类,就称为异常类


以前正常流程代码和问题处理代码相结合

现在将正常流程代码和问题处理代码分离,提高阅读性


其实异常就是java通过面向对象的思想将问题封装成了对象,用异常类对其进行描述

不同的问题用不同的类进行具体描述

 

异常的体系:

问题很多,意味着描述的类也很多,将其向上抽取,形成了异常体系

最终问题(不正常情况)就分成了两大类:一般不可处理的  和  可处理的两大类;


java中,对于不可处理的,一般用Error类来表示,对于 可处理的 , 一般用Exception来示。    

Throwable(可抛):无论是error,还是exception,都是问题,问题发生就应该抛出,让调用者知

道并处理(该体系的特点就在于Throwable及其所有的子类都具有可抛性;对于不具有可抛性的问

题是不能进行抛出的)


可抛性到底是什么?其实是通过两个关键字来体现的; throws 和 throw这两个关键字,凡是被这

两个关键字所操作的类和对象都具备可抛性。

一般不可处理的。Error

特点:是由jvm抛出的严重性问题。这种问题一般不针对进行处理,直接修改程序。

    

该体系的特点:子类的后缀名都是用其父类名作为后缀,阅读性很强。

1. 一般不可处理的。Error

2. 可处理的。Exception


下面的程序为throw关键字示例

    class Demo

    {

        public int method(int[] arr, int index)

        {

            if (arr == null)

            {

                throw new NullPointerException("这是一个空指针异常,哥们儿、你太疯狂啦!");

            }

            if (index >= arr.length)

            {

                throw new ArrayIndexOutOfBoundsException("数组的角标越界啦,哥们儿、你是不是疯啦?");

            }

            if (index < 0)

            {

                throw new ArrayIndexOutOfBoundsException("数组的角标不能为负数,哥们儿、你真的是疯啦!");

            }

            return arr[index];

        }

    }

    class  ExceptionDemo

    {

        public static void main(String[] args) 

        {

            int [] arr = new int[]{1,2,3};

            Demo d = new Demo();

            int num = d.method(arr,2);

            System.out.println("这是正确的输出" + num);

            int num1 = d.method(arr,3);

            System.out.println("这是异常的情况");

            System.out.println("这里是主程序结束的标志");

        }

    }


对于角标是整数不存在,可以用角标越界表示

对于负数为角标的情况,准备用负数角标异常来表示

负数角标这种异常在java中并没有定义过,那就按照java异常的创建思想,面向对象,将负数角标进行自定义描述,并封装成对象。这种自定义的问题描述称为自定义异常。


注意:如果让一个类称为一个异常类,则必须继承异常体系,因为只有继承异常体系的子类才有资格具备可抛性,才可以被两个关键字所操作(throw 和 throws

    class ArrayFuShuIndexException extends Exception

    {

        ArrayFuShuIndexException(){}

        ArrayFuShuIndexException(String msg)

        {

            super(msg);

         }

    }

    class Demo1

    {

        public int method(int[] arr, int index) throws ArrayFuShuIndexException

        {

            if (arr == null)

            {

                throw new NullPointerException("这是一个空指针异常,哥们儿、你太疯狂啦!");

            }

            if (index >= arr.length)

            {

                throw new ArrayIndexOutOfBoundsException("数组的角标越界啦,哥们儿、你是不是疯啦?");

            }

            if (index < 0)

            {

                throw new ArrayFuShuIndexException("数组的角标不能为负数,哥们儿、你真的是疯啦!");

            }

            return arr[index];

        }

    }

    class  ExceptionDemo1

    {

        public static void main(String[] args)  throws ArrayFuShuIndexException

        {

            int [] arr = new int[]{1,2,3};

            Demo1 d = new Demo1();

            int num = d.method(arr,2);

            System.out.println("这是正确的输出" + num);

            int num1 = d.method(arr,-1);

            System.out.println("这是异常的情况");

            System.out.println("这里是主程序结束的标志");

        }

    }

 

异常(Exception)的分类:

1. 编译时被检测的异常:只要是Exception和其子类都是,除了特殊子类RuntimeException体系;编译时异常问题一旦出现,希望在编译时就进行检测,让这种问题有对应的处理方式,这样的问题都可以针对性处理

2. 编译时不检测的异常(运行时异常):就是Exception中的RuntimeException和其子类;这种问题的发生,无法让功能继续,运算无法进行,更多的时候是调度者导致的。或者引发了内部状态的改变导致的。那么、这种问题一般不进行处理,直接编译通过,在运行时,让调用时的程序强制停止。让调用者对代码进行修正。

 

自定义异常时,要么继承Exception,要么继承RuntimeException

 

Throws 和 throw区别:

1. Throws 使用在函数上;Throw使用在函数内

2. Throws抛出的是异常类,可以抛出多个,用逗号隔开;throw抛出的是异常对象

 

异常处理的捕捉形式:

这是可以对异常进行针对性的处理方式

异常处理格式:

Try

{放需要被检测异常的代码}

Catch(异常类 变量) //该变量用于接收发生的异常对象

{真正处理异常的代码}

Finally

{一定会被执行的代码}


class ArrayFuShuIndexException extends Exception

{

    ArrayFuShuIndexException(){}

    ArrayFuShuIndexException(String msg)

    {

        super(msg);

    }

}

class Demo1

{

    public int method(int[] arr, int index) throws ArrayFuShuIndexException

    {

        if (arr == null)

        {

            throw new NullPointerException("这是一个空指针异常,哥们儿、你太疯狂啦!");

        }

        if (index >= arr.length)

        {

            throw new ArrayIndexOutOfBoundsException("数组的角标越界啦,哥们儿、你是不是疯啦?");

        }

        if (index < 0)

        {

            throw new ArrayFuShuIndexException("数组的角标不能为负数,哥们儿、你真的是疯啦!");

        }

        return arr[index];

    }

}

class  ExceptionDemo1

{

    public static void main(String[] args)

    {

        int [] arr = new int[]{1,2,3};

        Demo1 d = new Demo1();

        int num ;

        try

        {

            num = d.method(arr,-1);

        }

        catch (ArrayFuShuIndexException e)

        {

            System.out.println(e.getMessage());

            System.out.println("数组角标不能为负数");

        }

        catch (ArrayIndexOutOfBoundsException e)

        {

            System.out.println("数组越界");

        }/*

        catch (NullPointerException e)

        {

            System.out.println("传入的数组为空指针");

        }*/

        catch (Exception e)

        {

            e.printStackTrace();

        }

        finally

        {

            System.out.println("程序退出");

            System.exit(1);

        }

    }

}

注意:jvm的异常处理机制默认就是调用printStackStrace方法

但实际上,如果有生成日志的需求,均是使用第三方工具,例如log4jlog4jlog for java

注意:在多catch的情况下,父类的catch一定要放在子类的catch之下(代码上下位置)

 

异常处理原则;

1. 函数内容如果抛出需要检测的异常,那么函数上必须声明,否则必须在函数内用try catch捕捉,

   否则编译失败

2. 如果调用到了声明异常的函数,那么try catch要么throws,否则编译失败

3. 什么时候catch,什么时候throws

功能内容可以解决,用catch,解决不了,用throws告诉调用者,由调用者解决

4. 一个功能如果抛出多个异常,那么调用时,必须有多个catch进行针对性的处理;内部有几个

   需要检测的异常,就抛几个异常,抛出几个,就catch几个!

 

异常--finally代码块:通常用于关闭程序中打开的资源

有一种情况,finally代码块不会执行,就是在finally之前执行语句中,包含System.exit()语句。否则、无论是否发生异常,finally都一定会执行。

Try catch finally代码块组合特点:

1. Try catch finally

2. Try catch(多个),当没有必要资源需要释放的时候,使用这种方式

3. Try finally,可用于当出现异常的时候,确保资源立即释放掉,对于出现的异常,可能本类无法处理,交给其他的类来进行处理。


Void show() throws Exception

{

Try

{

Throw new Exception();

}

Finally

{}

}

下面是个例子

    class Demo2

    {

        public int method(int[] arr, int index)

        {

            if (index >= arr.length)

            {

                throw new ArrayIndexOutOfBoundsException("数组的角标越界啦,哥们儿、你是不是疯啦?");

            }

            return arr[index];

        }

    }

    class  ExceptionDemo2

    {

        public static void main(String[] args)

        {

            int [] arr = new int[]{1,2,3};

            Demo2 d = new Demo2();

            int num ;

            try

            {

                num = d.method(arr,10);

            }

            catch (ArrayIndexOutOfBoundsException e)

            {

                System.out.println("数组越界");

            }

            finally

            {

                System.out.println("程序退出");

                System.exit(1);

            }

        }

    }

Finally作用很大,例如 实际开发中连接数据库的代码,一旦查询的时候,发生异常,此时就可以在finally中关闭数据库的连接,如果不关闭,很容易耗尽数据库的连接资源。

 

异常应用:

 /*

    老师用电脑上课

 

    问题领域中涉及两个对象

    老师、电脑

 

    分析其中的问题。

    比如电脑蓝屏、冒烟啦

*/

    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();

        }

        Teacher(){}

 

        public void prelect() throws NoPlanException

        {

            try{

                comp.run();

                System.out.println("讲课");

            }catch (LanPingException e)

            {

                System.out.println(e.toString());

                comp.reset();

                prelect();

            }catch (MaoYanException e)

            {

                System.out.println(e.toString());

                test();

                throw new NoPlanException("对电脑进行维修,课时任务无法完成");

            }

        }

 

        public void test()

        {

            System.out.println("大家开始练习");

        }

    }

    class  ExceptionTest

    {

        public static void main(String[] args)

        {

            Teacher t = new Teacher("zhangsan");

            try

            {

                t.prelect();

            }

            catch (NoPlanException e)

            {

                System.out.println("换人...............");

            }

        }

    }

 


=====================================================

    class NoAddException extends Exception

    {}

 

    void addData(Data d) throws NoAddException

    {

        连接数据库

        try

        {

            添加数据,出现异常 SQLException

        }

        catch (SQLException e)

        {

            throw new NoAddException();

        }

        finally

        {

            关闭数据库

        }

    }

*/

 

异常注意事项:

1. 子类在覆盖父类方法时,父类的方法如果抛出了异常,那么子类的方法只能抛出父类的异常或者该异常的子类。

2. 如果父类抛出多个异常,那么子类只能抛出父类异常的子集

简单而言、实就是子类覆盖父类只能抛出父类的异常或者子集

注意:如果父类的方法没有抛出异常,那么子类覆盖时绝对不能抛。就只能try

 

Object:所有类的父类

Object是不断的抽取,具备着所有对象都具备的共性内容