11 异常

异常:是在运行时期发生的不正常情况...

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

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

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

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

其实异常就是java通过面向对象的思想将问题封装成了对象.

用异常类对其进行描述.

不同的问题用不同的类进行具体的描述,比如角标越界,空指针等.

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

最终问题(不正常情况)就分成了两大类.

 

class Demo
{
    public static void main(String[] args)
    {
        int[] arr = new int[3];
        System.out.println(arr[3]);//数组越界

        sleep(-5);
    }
    public static void sleep(int time)
    {
        if(time <0)
        {
            new FuTime();//就代表着时间为负的情况.
            //这个对象中会包含着问题的名称,信息,位置等信息
            //抛出
        }
        if(time>10000)
        {
            new BigTime();
            //抛出
        }
        System.out.println("我睡..."+time);
    }
}

class FuTime
{
}
class BigTime
{
}

抛出:对象需具备可抛性.

Throwable:无论是error还是异常,问题发生就应该可以抛出,让调用者知道并处理.

该体系的特点就在于Throwable及其所有的子类都具有可抛性.

可抛性到底指的是什么呢?怎么体现可抛性呢?

其实是通过两个关键字来体现的.

throws throw,凡是可以被这个关键字所操作的类和对象都具备可抛性.

1.一般不可处理的.Error

  特点:是由jvm抛出的严重性的问题.

    这种问题发生一般不针对性处理,直接修改程序.

2.可处理的.Exception

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

class Test
{
    public int method(int[] arr,int index)
    {
        if(arr==null)
            throw new NullPointerException("数组的引用不能为空!");
        if(index>=arr.length)
        {
            throw new ArrayIndexOutOfBoundsException(index);
        }
        if(index<0)
        {
            throw new ArrayIndexOutOfBoundsException("数组的角标不能为负数,哥们,你是真傻"+index);
        }
        
        return arr[index];
    }
}



class Demo
{
    public static void main(String[] args)
    {
        int[] arr = new int[3];
        Test d = new Test();
        int num = d.method(arr,-30);
        System.out.println("num="+num);
    }
}

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

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

而负数角标这种异常在java中并没有定义过.

那就按照java异常的创建思想,面向对象,将负数角标进行自定义描述,并封装成对象.

这种自定义的问题描述称为自定义异常.

注意:如果让一个类成为异常类,必须要继承异常体系,因为只有成为异常体系的子类,

才有资格具有可抛性,才可以被两个关键字所操作,throws throw

class FuShuIndexException extends Exception
{
    FuShuIndexException(){}
    FuShuIndexException(String mes){
        super(mes);
    }
}

class Test
{
    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 Demo
{
    public static void main(String[] args) throws FuShuIndexException
    {
        int[] arr = new int[3];
        Test d = new Test();
        int num = d.method(arr,-30);
        System.out.println("num="+num);
    }
}

异常的分类:

1.编译时被检测的异常.只要是Exception和其子类都是,除了特殊子类

RuntimeException体系.

这种问题一旦出现,希望在编译时就进行检测,让这种问题有对应的处理方式.

这样的问题都可以针对性的处理.

2.编译时不检测的异常(运行时异常):就是Exception中的RuntimeException和其子类.

这种问题的发生,无法让功能继续,运算无法进行,更多是因为调用者的原因导致的.

或者引发了内部状态的改变导致的.

那么这种问题一般不处理,直接编译通过,在运行时,让调用者调用时的程序强制停止.

让调用者对代码进行修正.

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

throws和throw的区别:

1.throws使用在函数上,throw使用在函数内.

2.throws抛出的是异常类,可以抛出多个,用逗号隔开.

throw抛出的是异常对象

 

异常处理的捕捉形式:

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

具体格式是:

try{

  //需要被检测异常的代码

}

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

{

  //处理异常的代码.

}

finally

{

//一定会被执行的代码

}

class FuShuIndexException extends Exception
{
    FuShuIndexException(){}
    FuShuIndexException(String mes){
        super(mes);
    }
}

class Test
{
    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 Demo
{
    public static void main(String[] args)
    {
        int[] arr = new int[3];
        Test d = new Test();
        try{
            int num = d.method(arr,-30);
            System.out.println("num="+num);
        }
        catch(FuShuIndexException e)
        {

        System.out.println("message:"+e.getMessage());
        System.out.println("message:"+e);       

        e.printStackTrace();
        //jvm默认的异常处理机制就是调用异常对象的这个方法

           System.out.println("负数角标异常");
        }
        System.out.println("over");//程序继续进行
    }
}

 一个try多catch的情况:

多catch父类的catch放在最下面,否则编译失败.

异常处理的原则:

1.函数内部如果抛出需要检测的异常,那么函数上必须要声明.否则必须咋函数内用

trycatch捕捉,否则编译失败.

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

3.什么时候try,什么时候catch,什么时候throws呢?

功能内容可以解决,用catch.

解决不了,用throws告诉调用者,由调用者解决.

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

内部有几个需要检测的异常,就抛几个异常,抛出几个,就catch几个.

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

class Demo
{
    public static void main(String[] args)
    {
    
        Test d = new Test();
        try{
            int num = d.show(-1);
            System.out.println("num ="+num);
        }
        catch(ArrayIndexOutOfBoundsException e)
        {
            System.out.println(e.toString());
            //return;//即使加了return,finally也一定会执行.
            System.exit(0);//退出jvm.
        }
        finally
        {
            System.out.println("finally");
        }
        System.out.println("over");
    }
}

finally经常被用到的一个地方:关闭(释放)资源

链接数据库,

查询,Exception

关闭链接,(无论是否异常,一定要执行),故通常放在finally中.

 

try catch finally 代码块组合特点:

1.try catch finally

2.try catch(多个)当没有必要资源需要释放时,可以不用定义finally.

3.try finally.

void show() throws Exception

{

  try

  {  

    //开启资源

    throw new Exception();

   //出现异常资源关闭不掉

  }

  finally

  {

    //关闭资源

  }
}

没有catch就需要声明.有catch就相当于处理了,不需要再throws

/*

毕老师用电脑上课.

问题领域中涉及两个对象.
毕老师,电脑.

分析其中的问题:
比如电脑蓝屏啦.冒烟啦.


*/

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);
            comp.reset();
            prelect();
        }
        catch(MaoYanException e)
        {
            System.out.println(e);
            test();
            //可以对电脑进行维修.

    //        throw e;
            throw new NoPlanException("课时进度无法完成,原因:"+e.getMessage());
        }

    }

    public void test()
    {
        System.out.println("大家练习");
    }
}

class Demo
{
    public static void main(String[] args)
    {
        Teacher t = new Teacher("毕老师");
        try{
            t.prelect();
        }
        catch(NoPlanException e)
        {
            System.out.println(e.toString()+"...");
            System.out.println("换人");
        }
    }
}
/*
class NoAddException extends Exception
{
}

void addData(Data d) thorws NoAddException //throws SQLException
{
    连接数据库
    try{
        添加数据.出现异常SQLException();
        }
    catch(SQLException e)
    {
        throw new NoAddException();
    }
    finally{
        关闭数据库
    }
}
*/

异常的注意事项:

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

或者该异常的子类.

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

简单说:子类覆盖父类只能抛出父类的异常或者子类或者子集.

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

 

class A extends Exception
{

}
class B extends A
{

}
class C extends Exception
{

}

Exception 
    |--A
        |--B
    |--C
class Fu
{
    void show() throws A
    {}
}
class Zi extends Fu
{
    //可以抛A,B或不抛,但不能抛C
    void show() throws C
    {}
}

class Test
{
    void method(Fu f)//Fu f= new Zi();
    {
        try{
            f.show();
        }
        catch(A a)
        {

        }
    }
}

class Demo
{
    public static void main(String[] args)
    {
        Test t = new Test();
        t.show(new Zi());
    }
}

 

posted on 2016-12-10 23:45  夜行锦衣  阅读(96)  评论(0编辑  收藏  举报

导航