【java高级】万字超详解异常

本文详细介绍了Java中的异常处理机制,包括异常的概述、异常的类和对象、编译时异常与运行时异常的区别、异常的处理方式(throws和try...catch)、finally关键字的使用,以及如何自定义异常。通过示例代码解析了异常处理的关键点,强调了异常处理对于程序健壮性的重要性。
摘要由CSDN通过智能技术生成

一.异常概述

我们先看一个简单的demo.

package com.sdnu.project1;

import javax.xml.bind.SchemaOutputResolver;

/**
 * @author Beyong
 * @Description Exception
 * @date 2021/05/22 10:18
 */

public class Demo1 {
    public static void main(String[] args) {
        int number1 = 1;
        int number2 = 0;
        System.out.println(number1/number2);
    }
}

结果:
在这里插入图片描述
以上程序就是我们所说的异常,它是在我们程序运行过程中发生了不正常的情况。以上的程序异常被打印在屏幕上,使得我们可以有针对的进行修改代码,增强了程序的健壮性,实际上,上面程序的异常由我们的JVM所打印的。

二.Java中异常以类和对象的形式存在

我们通过查看官方jdk1.8,发现每一个异常都是一个类。
在这里插入图片描述
既然是类,那么它就可以new一个对象出来,于是我们以上面的例子测试一下

package com.sdnu.project1;

/**
 * @author Beyong
 * @Description demo2
 * @date 2021/05/22 10:43
 */

public class Demo2 {
    public static void main(String[] args) {
        ArrayIndexOutOfBoundsException temp = new ArrayIndexOutOfBoundsException("kkk");
        System.out.println(temp);
    }
}

在这里插入图片描述
我们回到最开始的案例,实际上,当我们的JVM执行到System.out.println(number1/number2);
的时候,JVM会new一个对象出来,new ArithemeticException(" / by zero"),然后由JVM在控制台中打印出来,当然这个是我们看不见的情况之下由我们的JVM默默帮我们去做的。

再次理解!!!
比如有一个着火异常(类为着火)
(下面都为实例对象)
-> 小明家着火
-> 小李家着火
-> 小张家着火

三.异常的继承

在这里插入图片描述

  • Throwable为可抛出的
  • Error异常,由JVM抛出,终止程序,而Exception可进行处理
  • Exception的直接子类为编译时异常(注意时是RuntimeException以外的异常),必须在先进行处理,如果不处理,编译会报错,所以叫做编译时异常
  • RuntimeException及它的子类为运行时异常。

四.编译时异常及运行时异常的区别

编译时异常发生概率较高,而运行时异常发生概率较低。
举个例子。
编译时异常就像我们出门前,我们就可以知道这个时候是否下雨,我们就可以提前准备雨伞,而运行时异常就像我们平时走在马路上,突然高空抛下一个香蕉皮。

编译时异常也叫做受检异常(CheckedException),或受控异常。
运行时异常也叫做未受检异常(UnCheckException),或非受控异常。

五.异常的两种解决方案

(一).在方法声明的位置使用throws抛出,抛给上一级,谁调用就抛给谁。
(二).使用try …catch语句进行捕捉。
举个例子:
我们因为工作失误导致公司损失100元,我们由两种解决方案,一种就是我们报给上一级领导,另一种是我们自己解决,别人不知道。

注意:(1)当我们的异常往上抛得时候,我们的上一级也是有两种解决方安。
(2)我们的异常由main()抛给JVM的时候,JVM会终止我们的程序。

六.编译时异常必须处理

我们观察下面的程序,我们在还没有运行的情况之下,就出现了异常,这是因为我们的ClassNotFoundException是编译异常,必须要首先进行处理。

package com.sdnu.project1;

/**
 * @author Beyong
 * @Description demo3
 * @date 2021/05/22 21:22
 */

public class Demo3 {
    public static void main(String[] args){
        doSome();
    }
    public static void doSome() throws ClassNotFoundException{
        System.out.println("doSome");
    }
}

在这里插入图片描述

七.处理异常

我们来使用我们之前所说的两种方法来处理我们的异常。

(一)向上抛出

package com.sdnu.project1;

/**
 * @author Beyong
 * @Description demo3
 * @date 2021/05/22 21:22
 */

public class Demo3 {
    public static void main(String[] args) throws ClassNotFoundException{
        doSome();
    }
    public static void doSome() throws ClassNotFoundException{
        System.out.println("doSome");
    }
}

(二)try … catch

package com.sdnu.project1;

/**
 * @author Beyong
 * @Description demo3
 * @date 2021/05/22 21:22
 */

public class Demo3 {
    public static void main(String[] args){
        try{
            doSome();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
    public static void doSome() throws ClassNotFoundException{
        System.out.println("doSome");
    }
}

八.try…catch深入理解

我们这里有一个新的例子:

package com.sdnu.project1;

import java.io.FileInputStream;
import java.io.FileNotFoundException;

/**
 * @author Beyong
 * @Description Demo5
 * @date 2021/05/22 23:09
 */

public class Demo5 {
    public static void main(String[] args) throws FileNotFoundException{
        try{
            m1();
        } catch (FileNotFoundException e){
            e.printStackTrace();
        }
    }
    public static void m1() throws FileNotFoundException{
        System.out.println("m1 begin");
        m2();
        System.out.println("m1 over");
    }
    public static void m2() throws FileNotFoundException {
        System.out.println("m2 begin");
        new FileInputStream("D:\\test1.txt");
        System.out.println("m2 over");
    }
}

我们重点来看一下try…catch
在这里插入图片描述
其中的FileNotFoundException e 指明了一个FileNotFoundException 类型的引用 e,它指向了我们的异常对象。


注意:FileInputStream的一个构造函数如下图所示,这个构造函数会抛出异常,而且是编译异常,所以我们必须进行处理。

我们通过官方的jdk文档查阅FileNotFoundException,发现它是我们前面所过的IOException的一个子类,实际上,我们在catch的()中不仅可以写该异常具体的异常类型,我们也可以写该异常的父类型。

在这里插入图片描述

package com.sdnu.project1;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

/**
 * @author Beyong
 * @Description Demo5
 * @date 2021/05/22 23:09
 */

public class Demo5 {
    public static void main(String[] args)  {
        try{
            m1();
        } catch ( FileNotFoundException e){
            e.printStackTrace();
        }
    }
    public static void m1() throws FileNotFoundException{
        System.out.println("m1 begin");
        m2();
        System.out.println("m1 over");
    }
    public static void m2() throws FileNotFoundException {
        System.out.println("m2 begin");
        new FileInputStream("D:\\test1.txt");
        System.out.println("m2 over");
    }
}

改为FileInputStream的父类型:

在这里插入图片描述

我们也可以捕获多个异常,但是要注意捕获的异常子类型要在父类型之前。
在这里插入图片描述
在这里插入图片描述

九.上报还是捕获

只有一个原则:如果希望调用者处理,则选择上报。

十.异常对象的方法

(1)printStackTrace():取得异常的堆栈信息。
(2)getMessage():取得异常的描述信息。

十一.finally

finally关键字用来创建try后面要执行的代码,无论异常是否发生,都会执行。

在这里插入图片描述
我们通过更改文件路径,一次正确,一次故意写错误,也就是没有改文件,我们发现finally()都执行了。
在这里插入图片描述
在这里插入图片描述

当然,如果我们真的想退出,不执行finally,我们可以使用System.exit(0)来退出JVM
在这里插入图片描述
finally不执行了。
在这里插入图片描述

十二.自定义异常

方法:(1)一个类继承Exception或者RunTimeException
(2)该类提供两个构造方法,一个无参,一个带有String的参数

例子:

package com.sdnu.project1;

/**
 * @author Beyong
 * @Description Demo9
 * @date 2021/05/23 08:48
 */

public class MyException extends Exception{
    public MyException(){ }
    public MyException(String Ex){
        super(Ex);
    }
}
package com.sdnu.project1;

/**
 * @author Beyong
 * @Description Demo8
 * @date 2021/05/23 08:48
 */

public class Demo8 {
    public static void main(String[] args) {
        MyException temp = new MyException("hhh");
        String str = temp.getMessage();
        System.out.println(str);
        temp.printStackTrace();
    }
}

在这里插入图片描述
完整示例:

package com.sdnu.project1;

/**
 * @author Beyong
 * @Description Circle
 * @date 2021/05/23 09:01
 */

public class Circle {
    private int radius;
}


package com.sdnu.project1;

/**
 * @author Beyong
 * @Description Demo9
 * @date 2021/05/23 08:48
 */

public class MyException extends Exception{
    public MyException(){ }
    public MyException(String Ex){
        super(Ex);
    }
}

package com.sdnu.project1;

import java.util.Scanner;

/**
 * @author Beyong
 * @Description Demo8
 * @date 2021/05/23 08:48
 */

public class Demo8 {
    public static void main(String[] args) {
        System.out.println("Please input a radius of circle");
        Scanner input = new Scanner(System.in);
        int radius = input.nextInt();
        try{
            System.out.println(method(radius));
        } catch (MyException ex) {
            ex.getMessage();
            ex.printStackTrace();
        }
    }
    public static int method(int radius) throws MyException {
        if(radius <= 0){
            throw new MyException("半径异常");
        }
        return (int)(radius * radius * Math.PI);
    }
}



在这里插入图片描述

作者:Beyong    
出处:Beyong博客
github地址:https://github.com/beyong2019


本博客中未标明转载的文章归作者Beyong有,欢迎转载,但未经作者同意必须保留此段声明,且在文章明显位置给出原文连接,否则保留追究法律责任的权利。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值