Day26---学习Java第二弹

2021-08-05

Java异常方法

四、自定义异常

在 Java 中你可以自定义异常。如果要自定义异常类,则扩展Exception类即可,

因此这样的自定义异常都属于检查异常(checked exception)。如果要自定义非检查异常,则扩展自RuntimeException。

 

按照国际惯例,自定义的异常应该总是包含如下的构造函数:

一个无参构造函数

一个带有String参数的构造函数,并传递给父类的构造函数。

一个带有String参数和Throwable参数,并都传递给父类构造函数。

一个带有Throwable 参数的构造函数,并传递给父类的构造函数。

下面是IOException类的完整源代码,可以借鉴。

package java.io;
 
public class IOException extends Exception {
    static final long serialVersionUID = 7818375828146090155L;
 
    public IOException() {
    super();
    }
 
    public IOException(String message) {
    super(message);
    }
 
    public IOException(String message, Throwable cause) {
        super(message, cause);
    }
 
    public IOException(Throwable cause) {
        super(cause);
    }
}

finally块和return、

首先一个不容易理解的事实:在 try块中即便有return,break,continue等改变执行流的语句,finally也会执行。

finally中的return 会覆盖 try 或者catch中的返回值。

finally中的return或异常会抑制(消灭)前面try或者catch块中的异常。


详细处理情况介绍:

1.try-catch语句

     在Java中,异常通过try-catch语句捕获。其一般语法形式为:

try {
    // 可能会发生异常的程序代码
} catch (Type1 id1){
    // 捕获并处置try抛出的异常类型Type1
}
catch (Type2 id2){
     //捕获并处置try抛出的异常类型Type2
}

关键词try后的一对大括号将一块可能发生异常的代码包起来,称为监控区域。Java方法在运行过程中出现异常,

则创建异常对象。将异常抛出监控区域之 外,由Java运行时系统试图寻找匹配的catch子句以捕获异常

。若有匹配的catch子句,则运行其异常处理代码,try-catch语句结束。

匹配的原则是:如果抛出的异常对象属于catch子句的异常类,或者属于该异常类的子类,则认为生成的异常对象与catch块捕获的异常类型相匹配。

 

例1 捕捉throw语句抛出的“除数为0”异常。

public class TestException {
    public static void main(String[] args) {
        int a = 6;
        int b = 0;
        try { // try监控区域
            
            if (b == 0) throw new ArithmeticException(); // 通过throw语句抛出异常
            System.out.println("a/b的值是:" + a / b);
        }
        catch (ArithmeticException e) { // catch捕捉异常
            System.out.println("程序出现异常,变量b不能为0。");
        }
        System.out.println("程序正常结束。");
    }
}

 

 运行结果:程序出现异常,变量b不能为0。

程序正常结束。

例1 在try监控区域通过if语句进行判断,当“除数为0”的错误条件成立时引发ArithmeticException异常,

创建 ArithmeticException异常对象,并由throw语句将异常抛给Java运行时系统,由系统寻找匹配的异常处理器

catch并运行相应异 常处理代码,打印输出“程序出现异常,变量b不能为0。”try-catch语句结束,继续程序流程。

事实上,“除数为0”等ArithmeticException,是RuntimException的子类。而运行时异常将由运行时系统自动抛出,不需要使用throw语句。

 

例2 捕捉运行时系统自动抛出“除数为0”引发的ArithmeticException异常。

    public static void main(String[] args) {
        int a = 6;
        int b = 0;
        try {
            System.out.println("a/b的值是:" + a / b);
        } catch (ArithmeticException e) {
            System.out.println("程序出现异常,变量b不能为0。");
        }
        System.out.println("程序正常结束。");
    }
}

运行结果:程序出现异常,变量b不能为0。

程序正常结束。

例2 中的语句:

System.out.println("a/b的值是:" + a/b);

在运行中出现“除数为0”错误,引发ArithmeticException异常。运行时系统创建异常对象并抛出监控区域,转而匹配合适的异常处理器catch,并执行相应的异常处理代码。

由于检查运行时异常的代价远大于捕捉异常所带来的益处,运行时异常不可查。Java编译器允许忽略运行时异常,一个方法可以既不捕捉,也不声明抛出运行时异常。

 

例3 不捕捉、也不声明抛出运行

 

public static void main(String[] args) {
        int a, b;
        a = 6;
        b = 0; // 除数b 的值为0
        System.out.println(a / b);
    }

运行结果:

Exception in thread "main" java.lang.ArithmeticException: / by zero
at Test.TestException.main(TestException.java:8)

 

例4 程序可能存在除数为0异常和数组下标越界异常。

public class TestException {
    public static void main(String[] args) {
        int[] intArray = new int[3];
        try {
            for (int i = 0; i <= intArray.length; i++) {
                intArray[i] = i;
                System.out.println("intArray[" + i + "] = " + intArray[i]);
                System.out.println("intArray[" + i + "]模 " + (i - 2) + "的值:  "
                        + intArray[i] % (i - 2));
            }
        } catch (ArrayIndexOutOfBoundsException e) {
            System.out.println("intArray数组下标越界异常。");
        } catch (ArithmeticException e) {
            System.out.println("除数为0异常。");
        }
        System.out.println("程序正常结束。");
    }
}

运行结果:

intArray[0] = 0

intArray[0]模 -2的值: 0

intArray[1] = 1

intArray[1]模 -1的值: 0

intArray[2] = 2

除数为0异常。

程序正常结束。

 

例4 程序可能会出现除数为0异常,还可能会出现数组下标越界异常。程序运行过程中ArithmeticException异常类型是先行匹配的,因此执行相匹配的catch语句:

catch (ArithmeticException e){
      System.out.println("除数为0异常。");
 }

需要注意的是,一旦某个catch捕获到匹配的异常类型,将进入异常处理代码。一经处理结束,

就意味着整个try-catch语句结束。其他的catch子句不再有匹配和捕获异常类型的机会。

Java通过异常类描述异常类型,异常类的层次结构如图1所示。对于有多个catch子句的异常程序而言,

应该尽量将捕获底层异常类的catch子 句放在前面,同时尽量将捕获相对高层的异常类的catch子句放在后面。

否则,捕获底层异常类的catch子句将可能会被屏蔽。

RuntimeException异常类包括运行时各种常见的异常,ArithmeticException类和ArrayIndexOutOfBoundsException类都是它的子类。

因此,RuntimeException异常类的catch子句应该放在 最后面,否则可能会屏蔽其后的特定异常处理或引起编译错误。

 

posted @ 2021-08-05 19:58  zrswheart  阅读(30)  评论(0编辑  收藏  举报