浅析Java异常机制

版权声明:本文为奥维原创文章,未经允许不得转载.

概述

我们认为编写代码的时候不可避免的会产生一些逻辑上的错误,bug,所以长久以来程序员一直需要对产生的错误做一些处理.首先我们可能会考虑到可以使用if条件语句对一些情况做检查,但是这样对于面向对象的代码会导致业务代码和错误代码杂糅在一起等问题,而且有的错误你可以预知,但是你永远不能预知所有可能发生的错误.其次有人可能会想到用error-code这种机制来进行错误检测,通过返回值的不同来区分正确的情况和错误的情况.但是这样除了增加程序的冗杂性不谈,同时降低了程序的灵活性(e.g. 你为了要用整型数字1,2,3,4表示不同的情况,就要牺牲掉返回值,Java中只能有一个返回值).所以因为种种原因,异常机制产生了.

异常是什么

异常是计算机中可能出现的一些逻辑错误(e.g. 除数为0, 读写文件的时候找不到相应文件等等)在Java中,异常其实就是一些类的集合.下面这是一张Java的异常体系结构图.

1

异常总的来说可以分为两大类,分别是checked exception(必检)和unchecked exception(免检).其中unchecked exception 是Java语言不强制要求去编写代码捕获或者声明的异常,主要包括Error类和RuntimeException类以及他们的子类.而checked exception是程序员必须手动去处理(try/catch 或者 在方法签名处声明异常)的类型,主要包括除了unchecked exception类以外的类以及他们的子类. checked exception是Java语言特有的一种异常分类,其他语言都没有提供这种异常.这种异常被认为都是可以被处理和修复的,所以必须处理,否则无法通过编译,处理方式主要有一下两种:
  • 在方法签名处声明抛出该异常(throws关键字)
  • 程序使用try/catch块来捕获该异常
其中Error类及其子类一般是和JVM相关的问题,比如IOError LinkageError ThreadDeath等等类,这些异常程序员是几乎没法处理的,一般这些问题都是虚拟机错误,动态连接失败等等.这种类型的错误不太可能回复和捕捉,将直接导致应用程序终端.在程序中不应该对这种错误使用try/catch. 而RuntimeException和checked exception几乎都是可以补货的,常见的运行时异常类有(NullPointerException, IndexOutOfBoundsException,NumberFormatException等等),常见的必检异常有ClassNotFoundException,FileNotFoundException等等,必检异常如果不作处理那么在编译时期就不能通过.

为什么要设计异常处理机制

既然我们可以通过error-code这种机制或者是大量的if或者是switch语句来对错误进行检测和处理,为什么还要用异常机制呢.上面已经说了error-code或者switch/ifelse这两种方法有降低程序的灵活性,使得业务代码和检测错误代码杂糅等等很多缺点.所以有了异常机制. Java中,异常机制可以防止程序直接崩溃,帮助我们对错误进行分类,将错误处理和业务逻辑处理分离,帮我们准确定位异常出现的位置、原因,友好的向我们提示错误的原因,位置等等很多好处.在目前主流的成熟的高级编程语言中(e.g. Java, Python,, C++, Ruby等等)都提供了对异常处理的支持. Java中的异常处理机制error-code返回机制有这样几个重要的好处:
  • 如果是必检异常,程序员就必须用try/catch对他进行处理,或者抛出异常留待上一级(调用者)处理.也就是说程序员不可避免要对这类异常进行处理.而返回error-code的值这样的做法在这一点上就没有强制处理掉这个错误,程序员完全可以不理睬这个返回值
  • 使用异常处理机制,你的代码会更干净,清晰. 而返回error-code意味着你要实现若干个switch/case语句或者是ifelse语句,甚至是要实现很多方法调用栈上的switch/case语句,而且还使错误检查处理代码和业务逻辑代码混合,十分的不方便.
为什么要使用异常处理机制来解决我们Java编程中的错误还有一个很关键的好处就是,异常处理机制是允许抛出一个异常,然后自己本身不对异常做处理,这个抛出的异常会回传给调用者,留待调用者来处理,如果调用者还是不处理就会回传给调用者的调用者,如果调用者的调用者还是不作处理……一直回传到程序的入口(main方法),如果main方法也不知道怎么处理,yekeyishiyongthrows声明抛出异常,此时JVM做异常处理,JVM会打印异常的跟踪站信息,然后终止程序.这就是为什么如果我们不对异常做处理程序最后会自己中止的原因. 我们这样抛来抛去有什么好处?!!! 错误检测和错误处理的分离!!!!! 错误检测和错误处理的分离相当有用,比如说Java一些已经成型的类库,当我们在业务层调用这些类库中的类,方法的时候,类库本身根本不知道怎么处理出现的异常,因为出现这些异常我们是要返还给用户去看的,是要符合我们具体的实际的业务逻辑的,而Java底层的类库是脱离实际业务逻辑的.这个时候我们的底层类库就可以很潇洒的抛出一个异常直接交给业务层(调用者)去处理这些异常.实现错误检测和错误处理的分离.同时做错误处理的时候还可以进行进一步的分离,比如在catch块中,我们可以打印一些错误信息用于开发者去查看,再抛出一个错误,用于更上层(比如Android程序的界面层)去显示,这样可以做到对程序员和实际用户很友好,还不影响到底层与业务无关的类库.综上,方方面面的愿意使得我们去使用异常处理机制.

怎样使用Java中的异常处理机制

Java中的异常处理机制其实就是围绕try,catch,finally,throw,throws五个关键字做文章,下面做一一简介
  • try

    try块里面主要用于放置你觉得可能会产生异常的代码.如果执行try里面的业务逻辑代码出现了异常情况,系统会自动抛出一个异常对象.

  • catch

    catch块一般与try块配套使用,用于捕获try块中可能产生的异常(这个异常可以是系统抛出的也可以是你手动抛出的)并且对这个异常做一些处理.

  • finally

    finally块一般接在try/catch块之后,除非在try块,catch块中调用了退出JVM的方法比如System.exit(1);否则,不管在try/catch块中执行什么样的代码(包括return语句),异常处理的finally块总会被执行,所以一般我们可以使用finally回收一些已经打开了的物力资源(比如数据库连接,网络连接,文件),这些文件必须显式回收

  • throw

    这个主要用于我们自己手动抛出一个异常时使用,如果我们抛出的是checked exception(一般我们是自定义异常),那么和系统抛出异常的时候一样,我们要么使用try/catch块对这个抛出的异常做处理,要么就是在方法签名处做声明

  • throws

    throws用于在方法签名处做声明,表示我这个方法有可能抛出这种异常

总结

怎样使用Java中的异常处理机制说的比较简单一些,后面有空会改进,加上代码什么的.这次整体内容比较理论化,想好好掌握Java异常机制肯定少不了大量的代码训练.
月月说要给我打赏,就还是放了二维码,😝