黑马程序员——异常

来源:互联网 发布:icmp协议端口 编辑:程序博客网 时间:2024/06/05 20:33

——- android培训、java培训、期待与您交流! ———-

什么是异常?

就是程序运行时出现不正常情况。

异常由来:问题也是现实生活中一个具体的事物,也可以通过java的类的形式进行描述。并封装成对象。
其实就是java对不正常情况进行描述后的对象体现
对于问题的划分:两种:一种是严重的问题,一种是非严重的问题。

对于严重的:java通过Error类进行描述。
对于Error一般不编写针对性的代码对其进行处理。

对于非严重的:java通过Exception类进行描述。
对于Exception可以使用针对性的处理方式进行处理。

无论Error或者Exception都具有一些共性内容。
比如:不正常情况的信息,引发原因等。

异常中的体系结构:

Throwable
+++++|—Error
+++++|—Exception
+++++++++++|—RuntimeException

异常的语法:

java特供了特有的语句进行处理。

try{
需要被检测的代码;
}
catch(异常类 变量){
处理异常代码:(处理方式)
}
finally{
一定会执行的语句;
}

代码示例:

/*异常的使用:*/class ExceptionDemo {    int div(int a, int b){        return a / b;   //此处抛出new ArithmeticException()异常,算数异常    }}public class Demo {    public static void main(String[] args) {        ExceptionDemo d = new ExceptionDemo();        try{                //此处检测是否有new ArithmeticException()异常,将异常传给catch                int x = d.div(5,0);                 System.out.println(d.div(5, 0));        }        //此处捕获异常,相当于Exception e = new ArithmeticException();        catch(Exception e){             System.out.println("被除数不能为零");            //System.out.println(e.getMessage());   //    /by zero            //System.out.println(e.toString());//异常名称:异常信息            //e.printStackTrace();// 异常名称,异常信息,出现异常的位置。                                //jvm默认的异常处理机制,就是在调用printStackTrace()方法                                //打印异常的堆栈的跟踪信息        }        System.out.println("over");        /*         结果:            被除数不能为零            over         */    }}

throws关键字:

在编写程序时,如果某个函数在功能上可能会出现问题,
那么就在函数上通过throws声明该功能可能会出现问题,

这样做的好处是,让使用这个函数的方法必须try

如:

int div(int a, int b) throws Exception{//在功能上通过throws的关键字声明了该功能可能会出现问题    return a / b;   //  因为a/b,如果b的值为0,那么会出问题,所以得在函数上声明此函数可能出问题}

代码示例:

/*在函数上声明异常。便于提高安全性,让调用者进行处理,不处理则编译失败*/class ExceptionDemo {    int div(int a, int b) throws Exception{//在函数上通过throws的关键字声明了该功能有可能会出现异常        return a / b;       }}public class Demo {    public static void main(String[] args) //throws Exception    {        ExceptionDemo d = new ExceptionDemo();        try {//因为已经知道了div()功能有可以会出现异常,那么此处必须处理异常,            //否则该方法必须也用throws声明可能会出现异常            System.out.println(d.div(5, 4));        } catch (Exception e) {            System.out.println("被除数不能为零");        }        System.out.println("over");        /*         结果:            1            over         */    }}//简而言之:用throws关键字声明方法可能会出现异常,那么在使用该方法时,//要么处理异常,要么再用throws关键字声明可能会出现异常

多异常:

1.声明异常时,建议声明更具体的异常。这样处理的可以更具体。

2.对方声明几个异常,就对应有几个catch块。不要定义多余的catch块。
如果多个catch块中的异常出现继承关系,父类异常catch块放在最下面。
如果将父类异常放在最上面,那么会导致下面的异常永远不会执行得到,
那么,下面的异常就相当于废话一样

3.如果有多个catch块,出现异常时只能执行一个catch块,因为一旦发现异常
那么该程序就会直接跳到对应的catch块中执行,所以catch块只能执行一个。

建议:进行catch处理时,catch中一定要定义处理方式。
不要简单定义一句e.printStackTrace(),
也不要简单的就书写一条输出语句,因为这样客户在使用该软件发生异常的时候,
客户不知道这是什么东西,一个简单的输出语句不能解决客户的问题

代码示例:

/*多异常的使用*/class ExceptionDemo {    //在该方法上声明多个异常    int div(int a, int b) throws ArithmeticException,            ArrayIndexOutOfBoundsException {        int[] x = new int[a];        // 若此处出异常则抛出ArrayIndexOutOfBoundsException-->(数组角标越界异常)        System.out.println("x[4]=" + x[4]);        // 若此处出异常则抛出ArithmeticException -->(算数异常)        return a / b;    }}public class Demo {    public static void main(String[] args) {        ExceptionDemo d = new ExceptionDemo();        try {            d.div(5, 0);// 执行此方法导致-->算数异常            // d.div(4, 1);//执行此方法导致-->数组角标越界异常        } catch (ArithmeticException e) {            System.out.println("除数不能为零");        } catch (ArrayIndexOutOfBoundsException e) {            System.out.println("数组角标越界了");        }        System.out.println("over");        /*         结果:            x[4]=0            除数不能为零            over         */    }}

throw关键字:

当在函数内部出现了throw抛出异常对象,那么就必须要给出对应的处理动作。
要么在内部try catch处理。
要么在函数上声明,让调用者处理。

一般情况下,函数内抛出异常,函数上需要声明。

自定义异常:

必须是自定义类继承Exception、Error、Throwable

继承它们的原因:
异常体系有一个特点:因为异常类和异常对象都被抛出。
他们都具备可抛性,这个可抛性是Exception、Error或Throwable
体系中的独有特点。

只有这个体系中的类和对象才可以被throws和throw操作。

如何定义异常信息呢?
因为父类中已经把异常信息的操作都完成了。
所以子类只要在构造时,将异常信息通过super语句传给父类
那么就可以直接通过getMessage或toString方法获取自定义的异常信息。

代码示例:

/*需求:在本程序中,对于除数是-1,也视为是错误的,是无法进行运算的,那么就需要对这个问题进行自定义的描述。*///创建一个FuShuException类,继承Exception,那么这个类就成为一个自定义异常类class FuShuException extends Exception{    private int value;    public FuShuException(String string,int value){        //子类只要在构造时,将异常信息通过super语句传给父类        //那么就可以直接通过getMessage或toString方法获取自定义的异常信息。        super(string);        this.value = value;    }    public int getValue(){        return value;    }}class ExceptionDemo {    int div(int a, int b) throws FuShuException {        //如果输入的b小于0,则抛出异常,        //同时函数上通过throws的关键字声明该功能有可能会出现异常        if(b<0)            //手动通过throw关键字抛出一个自定义异常对象            throw new FuShuException("此异常为负数异常",b);        return a / b;    }}public class Demo {    public static void main(String[] args) {        ExceptionDemo d = new ExceptionDemo();        try {            d.div(5, -9);        } catch (FuShuException e) {            //通过toString方法获取自定义的异常信息。            System.out.println(e.toString());//结果:此异常为负数异常            //调用自定义异常中错误的值            System.out.println("错误的负数是"+e.getValue());//结果:错误的负数是-9        }        System.out.println("over");    }} /*            结果                FuShuException: 此异常为负数异常                错误的负数是-9                over */

throws和throw区别:

throws定义在函数上。
throw定义在函数内。

throws后面跟异常类。可以跟多个,用逗号隔开。
throw后面跟异常对象。

特殊的异常RunTimeException

RunTimeException异常

Exception中有一个特殊的子类异常RunTimeException 运行时异常。

如果函数内容抛出该异常,函数上可以不用声明,编译一样通过。

如果在函数上声明了该异常。调用者可以不用进行处理,编译一样通过。

之所以不用函数声明,是因为不需要让调用者处理。
当该异常发生,希望程序停止。因为在运行时,出现了无法继续运算的情况,希望停止后,
对代码进行修正。

如:

class ExceptionDemo {    int div(int a, int b) //throws ArithmeticException//此处声明异常,调用者可以不用进行处理    {        if(b == 0)            throw new ArithmeticException("除数为0");//此处抛出异常,函数上可以不用声明        return a / b;    }}

自定义异常时:如果该异常的发生,无法再继续进行运算,
就让自定义异常继承RunTimeException。

代码示例:

/* RuntimeException异常的演示:*/class FuShuException extends RuntimeException {//继承RuntimeException异常    private int value;    public FuShuException(String string, int value) {        super(string);        this.value = value;    }    public int getValue() {        return value;    }}class ExceptionDemo {    int div(int a, int b) // throws FuShuException//因为自定义异常继承的是RuntimeException,所以函数可以不用声明异常。因为发成异常时不希望被处理    {        if (b < 0)            throw new FuShuException("此异常为负数异常", b);//抛出异常        if (b == 0)            throw new FuShuException("0不能为除数", 0);        return a / b;    }}public class Demo {    public static void main(String[] args) {        ExceptionDemo d = new ExceptionDemo();        // try {        d.div(5, 0);//因为函数没有声明异常,所以这里可以不用try处理        // } catch (FuShuException e) {        // System.out.println(e.toString());        // System.out.println("错误的负数是"+e.getValue())        // }        System.out.println("over");    }}/*运行结果:            Exception in thread "main" FuShuException: 0不能为除数            at ExceptionDemo.div(Demo.java:24)            at Demo.main(Demo.java:34)*/

finally

finally:定义一定执行的代码。 通常用于关闭资源

finally使用的例子:

 public void method(){    try{        连接数据库        //数据操作可能会抛出一个异常 throw new SQLException();        //导致程序无法继续向下运行,最终会导致无法关闭数据库        数据操作    }    catch(SQLException e){        对数据库异常进行处理;        throw new NoException();//处理完异常了之后,必定要返回一个结果    }    finally{        关闭数据库   //将关闭数据库放在finally中,不管数据操作是否成功,都肯定会关闭数据库肯定    } }

代码示例:

class FuShuException extends Exception {    public FuShuException() {    }    public FuShuException(String string) {        super(string);    }}class ExceptionDemo {    public int div(int a, int b) throws FuShuException    {        if (b < 0)            throw new FuShuException("除数不能为负数");        return a / b;    }}public class Demo {    public static void main(String[] args) {        ExceptionDemo ed = new ExceptionDemo();        try {            ed.div(5, -2);        } catch (FuShuException e) {            System.out.println(e.toString());            //在此处加了个return语句后,System.out.println("over")就不会执行,            //但是finally中的一句还会执行            return;        }        //finally中的数据肯定会执行        finally {            System.out.println("finally");        }        System.out.println("over");        /*         结果:            FuShuException: 除数不能为负数            finally         */    }}

异常的三种使用格式:

第一种格式try{}catch{}第二种格式try{}catch{}finally{}第三种格式try{}finally{}//第三种格式的一般使用方式://不管程序是否检测到异常,都必须关闭资源//如:class ExceptionDemo {    public void function() throws Exception{        try{            throw new Exception();        }finally{            //关闭资源        }    }}

异常在子父类覆盖中的体现:

1.子类在覆盖父类时,如果父类的方法抛出异常,那么子类的覆盖方法,只能抛出父类的异常或者该异常的子类,或者进行try处理。
2.如果父类方法抛出多个异常,那么子类在覆盖方法时,只能抛出父类的异常子集,或者该异常的子类,或者进行try处理。
3.如果父类或者接口的方法中没有异常抛出,那么子类在覆盖方法时,也不可以抛出异常。
如果子类方法发生了异常。就必须要进行try处理,绝对不能抛出。

代码示例:

/* * *需求:有一个圆形和长方形。 *都可以获取面积。对于面积如果出现非法的数值,视为是获取面积出现问题。 *问题通过异常表示。 * *思路: *1.因为三角形和长方形都是图形,他们就应该具备求面积的方法, *  所以将求面积的方法定义为抽象的 *   *2.定义三角形和长方形类,继承图形类,实现图形类中求面积的方法 * *3.在求面积的时候可能会出现非法值,例如:圆的半径= -2。所以应该自定义 *  一个异常类,判断如果输入的数值不非法,那么直接抛出异常。 *   *4.因为数值非法这个异常的不可处理的,所以自定义的异常应该继承RuntimeException */abstract class TuXing { // 图形类    abstract double getMianJi();// 获取面积方法}class FuShuException extends RuntimeException {// 自定义异常    public FuShuException() {    }    public FuShuException(String s) {        super(s);//将异常的信息传递给父类    }}class YuanXing extends TuXing {// 圆形类    private double r;//半径    public YuanXing() {        this.r = 1.0;    }    public YuanXing(double r) {        if (r <= 0)// 如果输入的值不合法,则抛出异常,让程序终止            throw new FuShuException("不能传入负数或者零");        this.r = r;    }    public double getMianJi() // throws Exception 此处不能抛异常,因为子类覆盖父类方法时, 只能抛父类异常的子类或者自己。如果父类没有抛出异常,那么子类也不可以抛    {        return r * r * Math.PI;    }}class ChangFangXing extends TuXing {// 长方形类    private double a, b;    public ChangFangXing() {        a = 1;        b = 1;    }    public ChangFangXing(double a, double b) {        if (a <= 0 || b <= 0)// 如果输入的值不合法,则抛出异常,让程序终止            throw new FuShuException("不能传入负数或者零");        this.a = a;        this.b = b;    }    double getMianJi() // throws Exception 此处不能抛异常,因为子类覆盖父类方法时,    // 只能抛父类异常的子类或者自己。如果父类没有抛出异常,那么子类也不可以抛    {        return a * b;    }}public class Demo {    public static void main(String[] args) {        TuXing t = new YuanXing(3);        printMianJi(t);        TuXing t1 = new ChangFangXing(12, -4);//此处传入了一个负数,会导致出现异常,使得程序终止        printMianJi(t1);        /*         结果:            28.274333882308138            Exception in thread "main" FuShuException: 不能传入负数或者零            at ChangFangXing.<init>(Demo.java:60)            at Demo.main(Demo.java:77)         */    }    public static void printMianJi(TuXing t) {        System.out.println(t.getMianJi());    }}

总结:

异常是什么?是对问题的描述。将问题进行对象的封装。

异常体系:
Throwable
++++|—–Errow
++++|—–Excepting
+++++++|—–RunTimeException

异常体系的特点:异常体系中的所有类以及建立的对象都具备可抛性。
也就是说可以被throw和throws关键字所操作。
只有异常体系具备这个特点。

throw和throws的用法:

throw定义在函数内,用于抛出异常对象。
throws定义在函数上,用于抛出异常类,可以抛出多个,用逗号隔开。

当函数内容有throw抛出异常对象,并未进行try处理。必须要在函数上声明,否则编译失败。
注意:RunTimeException除外。也就说,函数内如果抛出RunTimeException异常或者RunTimeException
异常的子类,函数上可以不用声明。

如果函数声明了异常,调用者需要进行处理。处理方式可以throws,可以try。

异常有两种:
编译时被检测异常
该异常在编译时,如果没有处理(没有throw也没有try),那么编译失败
该异常被标识,代表着可以被处理。
运行时异常(编译时不检测)
在编译时,不需要处理,编译器不检查。
该异常的发生,建议不处理,让程序停止。需要对代码进行修正。

注意:
1,finally中定义的通常是,关闭资源代码,因为资源必须要释放
2,finally只有一种情况不会执行。当程序执行到System.exit(0)时,fianlly不会执行。
//System.exit(0) –> 系统退出。jvm结束。

自定义异常:
定义类继承Exception或者RunTimeException
1,为了让自定义类具备可抛性。
2,让该类具备操作异常的共性方法。

/*当要定义自定义异常的信息时,可以使用父类已经定义好的功能。异常的异常信息传递给父类的构造函数*/class MyException extends Exception{    public MyException(String string){        super(string);    }}

异常的好处:
1,将问题进行封装。
2,将正常流程代码和问题处理代码相分离,方便与阅读。

异常的处理原则:
1,处理方式有两种:try 或者 throws。
2,调用到抛出异常的功能时,抛出几个,就处理几个(不要多处理或者少处理)
一个try对应多个catch。
3,多个catch中,父类的catch放到最下面。
4,catch内,需要定义针对性的处理方式,不要简单的定义printStackTrace,输出语句。
也不要不写。

//当捕获到的异常,本功能处理不了时,可以继续在catch中抛出。try{    throw new AException();}catch(AException e){    throw e;}
/*如果该异常处理不了,但并不属于该功能出现的异常。可以将异常转换后,再抛出和该功能相关的异常。或者异常可以处理,但需要将异常产生的和本功能相关的问题提供出去,让调用者知道,并处理。也可以将捕获异常处理后,转换为新的异常。*/try{    throw new AException();}catch(AException e){    //对AException处理。然后再抛BException    throw new BException();}

在子父类覆盖时:
1,子类抛出的异常必须是父类异常的子类或者子集。
2,如果父类或者接口中没有异常抛出时,子类覆盖出现异常,只能try,不能抛

0 0
原创粉丝点击