Java异常处理机制全网最详细总结(小白也能理解)

一、异常的定义与作用
定义:在程序运行时产生了问题,从而不得不中断程序的运行,这就是异常。就好比你今天准备出去爬山,结果爬着爬着却突然下雨了,这就是出现了异常。
作用:通过打印出的异常信息,我们可以知道是哪里的代码出现了问题,并大概了解为什么会出现这个问题。

二、产生异常的几种情况
1、Java内部产生的异常,如虚拟机产生了异常。
2、我们自己编写的程序出现了异常,比如空指针异常、文件未找到异常等等。
3、使用throw语句主动生成的异常。

三、抛出异常和捕获异常的定义
Java是通过面向对象的方式来处理异常的,当一个方法运行的时候产生了一个异常,那么这个方法会生成一个代表该异常的对象,然后把它提交给运行时系统,运行时系统去寻找相应的代码来处理该异常。
1、抛出异常:生成异常对象,并把它提交给运行时系统的这个过程称为抛出异常。
2、捕获异常:运行时系统在方法的调用栈中去查找,找到能够处理该异常的对象的这个过程称为捕获异常。

四、异常处理类体系
在Java中进行异常处理,依靠的是Java内部封装好的异常处理类。这些类都是Throwable类的子类,也就是说Throwable这个类位于异常处理类机制的顶层。该类有两个子类分支,即ErrorException,分别表示错误和异常。
Error 类指正常情况下不大可能会出现的情况,绝大部分的 Error 都会导致程序处于非正常、不可恢复状态。所以不需要被开发者捕获。一般指 JVM出现了错误,如堆栈溢出,我们一般不需要去关注这个类。
Exception 类是程序正常运行过程中可以预料到的意外情况,并且应该被开发者捕获并进行相应的处理,所以这个就是需要我们去重点关注并处理的异常。
Exception类下面包括运行时异常(也叫不受检查的异常)和非运行时异常(也叫编译时异常、受检查异常)两个分支。如下图所示:
在这里插入图片描述
(1)运行时异常
其中所有的运行时异常类都是RuntimeException类(RuntimeException类继承了Exception类)及该类的子类,运行时异常是在我们正常的编码中可以避免的逻辑错误,可以根据需要来判断是否需要捕获,该异常并不会在编译期强制要求捕获处理,如 NullPointerException、IndexOutOfBoundsException等。
(2)非运行时异常
非运行时异常类则是除RuntimeException类 以外的所有异常类,这些异常类属于Exception类及该类的子类,
如IOException、ClassNotFoundException 等。非运行时异常一般必须得处理,如果不处理的话,程序编译的时候就通过不了。

下图是常见的运行时异常和非运行时异常。
在这里插入图片描述
在这里插入图片描述

五、异常处理机制
Java异常处理机制主要是通过五个关键字,即try、catch、finally、throw、throws来实现的。
(1)try、catch主要是用来捕获和处理异常的;
(2)finally主要用于在任何情况下都必须执行的代码,也就是说不管你try块中有没有出现异常,我这些代码都必须要执行,那么这些代码就适合写在finally块中。比如关闭一些我们在try块中打开过的物理资源等等;
(3)throw主要是用于我们开发者直接手动抛出一个异常对象;
(4)throws主要用于声明所在的方法可能会出现的异常,简单来说就是告知这个方法的调用者,我这个方法可能会出现这个异常,但是我自己没有对这个方法进行异常处理,所以如果你要想调用我的话,那你记得处理我可能会抛出的这些异常。

异常处理程序的基本使用模板:

public static void test() throws ExceptionType1 {
        try {
            //可能出现异常的代码块
        } catch(ExceptionType2 e) {
            //对捕获的异常进行处理的代码块
            e.printStackTrace();//打印异常信息
        } catch (ExceptionType3 e) {
            //对捕获的异常进行处理的代码块
            throw(e);    // 再抛出这个"异常"
        } finally {
            //释放资源代码块
        }
    }

在以上语法中,把可能引发异常的语句封装在 try 语句块中,用以捕获可能发生的异常。catch 后的( )里放匹配的异常类,指明该catch 语句块可以处理的异常类型,发生异常时产生该异常类的实例化对象。

在catch语句块中,我们可以使用以下 3 个方法输出相应的异常信息:
printStackTrace() 方法:指出异常的类型、性质、栈层次及出现在程序中的位置,是最常用的一种方法。
getMessage() 方法:输出错误的性质。
toString() 方法:给出异常的类型与性质。

try catch finally 语句块的执行情况可以细分为以下 3 种情况:
(1)如果 try 代码块中没有拋出异常,则执行完 try 代码块之后直接执行 finally 代码块,然后执行 try catch finally 语句块之后的语句。
(2)如果 try 代码块中拋出异常,并被 catch 子句捕捉,那么会在try 代码块拋出异常的地方终止执行,转而执行相匹配的 catch 代码块,之后执行 finally 代码块。如果 finally 代码块中没有拋出异常,则继续执行 try catch finally 语句块之后的语句;如果 finally 代码块中拋出异常,则把该异常传递给该方法的调用者。
(3)如果 try 代码块中拋出的异常没有被任何 catch 子句捕捉到,那么将直接执行 finally 代码块中的语句,并把该异常传递给该方法的调用者。

throws 和 throw 在使用上的几点区别:
(1)throws 用来声明一个方法可能抛出的所有异常信息,表示出现异常的一种可能性,但并不一定会发生这些异常;throw 则是指拋出的一个具体的异常类型,执行 throw 就一定会抛出了某种异常对象;
(2)throws一次可以抛出多个异常,各异常之间用,分隔即可。而throw一次只能抛出一个异常;
(3)throws用于方法头,表示的只是异常的申明,而throw用于方法体内部,抛出的是一个异常对象;
(4)throws抛出异常时,它的上级调用者要么继续向上申明抛出异常,要么就对异常进行捕获,不然会编译报错。而throw的话,可以不申明或不捕获(但这是非常不负责任的方式)编译器也并不会报错,但是秉着负责的态度,还是需要我们自己去捕获相关的异常,而后再对其进行相关包装,最后将包装后的异常信息抛出。

异常处理程序使用注意事项:
(1)异常处理语法结构中只有 try 块是必需的,也就是说,如果没有 try 块,就不会有后面的 catch 块和 finally 块;
(2)catch 块和 finally 块都是可选的,但 catch 块和 finally 块至少出现其中之一,也可以同时出现;
(3)可以有多个 catch 块,且多个 catch 块必须位于 try 块之后,finally 块也必须位于所有的 catch 块之后;
(4)finally 块与 try 块匹配时,此种情况会导致异常丢失,一般不常使用;
(5)当捕获的多个异常类之间存在父子关系时,捕获异常时一般需要先捕获子类异常,再捕获父类异常。子类异常必须在父类异常的前面,否则子类异常就会捕获不到;
(6)try 块和catch块里声明的变量只是代码块内的局部变量,它只在当前所在的块内有效,其它地方不能访问该变量;
(7)除非在 try 块、catch 块中调用了退出虚拟机的方法System.exit(int status)等特殊情况,否则不管在 try 块或者 catch 块中执行怎样的代码,出现怎样的情况,异常处理的 finally 块总会执行;
(8)通常情况下不在 finally 代码块中使用 return 或 throw 等导致方法终止的语句,否则将会导致 try 和 catch 代码块中的 return 和 throw 语句失效。详细讲解参考这篇博客。

六、自定义异常
当Java内置的异常类型都不能满足我们程序设计的需求时,这时候我们就可以自定义一个我们想要的异常了。
如果我们想要实现的自定义异常属于运行时异常那就继承RuntimeException或其子类,如果属于非运行时异常,那就继承Exception类。最后再在我们的自定义异常中实现两个构造方法就可以了,一个是无参的默认构造方法,另一个构造方法以字符串的形式接收一个定制的异常消息,并将该消息传递给超类的构造方法。
代码如下:

//自定义异常MyException
public class MyException extends Exception{
    public MyException() {
    }

    public MyException(String message) {
        super(message);
    }
}

//使用MyException
public class Test {
    public static void main(String[] args) throws MyException {
        test();
    }
    public static void test() throws MyException {
        throw new MyException("我是自定义异常");
    }
}

上述程序输出结果:
在这里插入图片描述

  • 22
    点赞
  • 92
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值