Java异常(三十五)

异常

异常,就是不正常的意,在程序中指的是程序在执行过程中,出现的非正常的情况,最终导致程序停止。

异常的体系

在java中,异常的要类是java.lang.Throwable,他有两个直接子类,java.lang.Errorjava.lang.Exception,两个类,这三个都是类,不是接口。并且,所有的和异常相关的都是类。
java.lang.Throwable里面我们常用的有三个方法:

  • public void printStackTrace(),打印异常的详细信息,打印出异常的类型,异常的信息,异常的出现的位置,我们在开发和调试的时候,用的最多的就是这个方法。
  • public String getMessage(),只打印异常的描述信息。
  • public String toString(),打样印异常的类型,还有异常的描述信息。

异常的分类

异常的分类,我们通常说的异常的分类,一般指的都是Exception类或者Exception下面的子类,并且Exception分为两种类型:

运行时异常:(RuntimeException) 在运行的时候,会暴露出来,但是在编译的时候,不会提示。可以不用我们处理。
编译时异常:(Exception)在编译的时候出现的异常,说明必须要处理,如果不处理的话,编译就会不通过,会编译失内败。

异常的处理

处理异常有的五个关键字:trycatchfinallythrowthrows
我们处理异常的方式有两种:

1、try ... catch ,在try里面捕获异常,在catch里面处理异常。
2、throws,声明异常。

声明异常throws

声明异常,就是将问题的标识出来,然后报告给方法的调用者,如果方法里面出现了编译时导演,没有进行捕获,而是选择了抛出异常,也就是声明异常,那么,这个异常就会交给调用者出理。
使用的格式:

修饰符 返回值类型 方法名(参数)throws 异常类型1,...异常类型n { }

例:

    public static void test() throws InterruptedException {
        //这是一个编译时异常,但是没有进行捕获,直接抛出
        Thread.sleep(1000);
    }

异常抛出以后,可以在调用者那里直接也进行抛出,也可以进行捕获。

    public static void main(String[] args) throws InterruptedException {
        test();
    }
    public static void main(String[] args){
        try {
            test();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

异常可以一直向上抛出,一直到JVM里面。


可以自己声明异常:

    public static void main(String[] args) throws IOException, InterruptedException {
        test(0);
    }

    public static void test(Integer num) throws InterruptedException, IOException {
        //这是一个编译时异常,但是没有进行捕获,直接抛出
        Thread.sleep(1000);
        if (num == 0) {
            throw new IOException("输入的是一个0");
        }

    }

运行的结果:

上面的一段代码中,我们抛出了两个异常,一个是线程类必须要处理的异常,一个是自己声明的异常,所以如果我们要抛出多个异常的时候,我们要用 , 隔开。


其实在抛出异常的时候,我们不用抛出那么细致的异常,我们可以直接抛出一个大的异常类,比如Exception类。并且运行的结果还是一样的。

捕获异常 try...catch

如果异常出现,我们必须得处理,不会程序会立刻终止。用try...catch方式就是捕获异常,我们可以对可以出现异常的语句进行异常的捕获。
语法如下:

    try{
        //可能出现异常的语句
    }catch{
        //出现异常之后的处理的方法
    }
  • try:这个代码块当中编写可能出现的异常。
  • catch:这个代码块当中对异常进行捕获,并且进行处理。

他们必须要一起使用,不能单个使用!
例子:

    //对异常进行捕获,然后打印出详细的信息
    try {
        Thread.sleep(1000);  //编译时异常
    } catch (InterruptedException e) { //但是如果没有异常,就会继续执行下面的代码。
        e.printStackTrace();
    }
    //也可以对运行时异常进行处理
    try {
        int i = 1 / 0;              //运行时异常
    } catch (Exception e) {
        e.printStackTrace();
    }

执行的结果:

上面图中的异常信息,就是Throwable里面的printStackTrace()打印出来的,包含了异常的信息,异常的类型,并且包含了异常出现的行数。

finally 代码块

finally:我们在处理一些特定的事情的时候时,不管我们的代码是否出现异常,我们都必须要执行。并且有的时候,我们在执行代码的时候,如果在try里面出现了异常,那么从出现异常的地方开始,后台的代码都不会执行,直接会跳过,执行catch里面的内容,这是我们不能容忍的,所以出现了finally代码块。把我们必须要处理的代码放进去,不管会不会出现异常,都必须要执行这一段代码。
语法:

    try{
        //可能出现异常的语句
    }catch{
        //如果出现异常执行的逻辑
    }finally{
        //不管出不出现异常都要执行的代码
    }

例:
没有使用finally的时候:

    try {
        int i = 1 / 0;
        System.out.println("我想输出这一句话");
    } catch (Exception e) {
        e.printStackTrace();
    }

结果:

在使用finally的情况:

    try {
        int i = 1 / 0;
    } catch (Exception e) {
        e.printStackTrace();
    }finally {
        System.out.println("我想输出这一句话");
    }

结果:

自定义异常

在我们实际工作中,java自带的异常总是不够我们用,所以我们这个时候,就必须要自定义异常了。

    //可以继承Exception (编译时异常),RuntimeException(运行时异常)
    public class ZeroException extends Exception {
        //自定义的异常的时候,我们一般都是这个格式 
        //来一个无参构造方法,一个有参构造方尘,然后都是调用父类的构造方法
        public ZeroException() {
            super();
        }
        public ZeroException(String message) {
            super(message);
        }
    }

上面是我们自己定义的异常,下面让我们看看java定义的异常类,NullPointerException。(空指针异常)

    public class NullPointerException extends RuntimeException {
        private static final long serialVersionUID = 5162710183389028792L;

        /**
         * Constructs a {@code NullPointerException} with no detail message.
         */
        public NullPointerException() {
            super();
        }

        /**
         * Constructs a {@code NullPointerException} with the specified
         * detail message.
         *
         * @param   s   the detail message.
         */
        public NullPointerException(String s) {
            super(s);
        }
    }

使用我们自己定义的异常:

    int i = 0;
    if (i == 0) {
        try {
            throw new ZeroException("不可以为0");
        } catch (ZeroException e) {
            e.printStackTrace();
        }
    }

运行的结果:

使用异常时候需要注意

运行时异常被抛出可以不处理。即不捕获也不声明抛出。
如果finallyreturn语句,永远返回finally中的结果,避免该情况。
如果父类抛出了多个异常,子类重写父类方法时,抛出和父类相同的异常或者是父类异常的子类或者不抛出异常。
父类方法没有抛出异常,子类重写父类该方法时也不可抛出异常。此时子类产生该异常,只能捕获处理,不能声明抛出。
多个catch中的异常不能相同,并且若catch中的多个异常之间有子父类异常的关系,那么子类异常要求在上面的catch处理,父类异常在下面的catch处理。



细节决定成败!
个人愚见,如有不对,恳请扶正!

猜你喜欢

转载自www.cnblogs.com/xdtg/p/12717140.html