深入理解java异常处理机制的原理和开发应用

  Java异常处理机制其最主要的几个关键字:try、catch、finally、throw、throws,以及各种各样的Exception。本篇文章主要在基础的使用方法上,介绍了如何更加合理的使用异常机制。 

try-catch-finally

    try-catch-finally块的用法比较简单,使用频次也最高。try块中包含可能出现异常的语句(当然这是人为决定的,try理论上可以包含任何代码),catch块负责捕获可能出现的异常,finally负责执行必须执行的语句,这里的代码不论是否发生了异常,都会被执行。

    针对这部分,因为很基础,所以就提几点比较关键的建议:

      1、当你在写try-catch语句的时候,脑子里是知道自己要去针对哪种异常进行处理的,不要只是以防万一,加了个catch(Exception e),这是毫无意义的。并且,一个try块中可能有多个异常,对于每一类异常,要分别写一个catch进行捕获。       

      2、针对可能出现异常的语句进行try-catch,大段代码的try-catch会非常不利于维护代码时定位异常可能发生的位置,对于肯定不会发生异常的稳定的代码,不需要放在try块中。

      3、try-catch虽然在功能上,可以成为流程控制的工具,达到条件分支的效果。但相比于if-else语句,java的异常处理机制基于面向对象的思想,使用过程中需要更多的时间与空间的开销,所以不要用异常机制去做基本的条件判断,只有在程序会因为异常而中断时进行捕获和处理。

      4、finally块中永远不要写return语句,因为finally块中总是最后执行,他会改变预期在trycatch块中的返回值(举个例子,你在catch中捕获了一个异常并抛出e,又在finally语句中return true,这样你抛出的异常就"消失"了,因为当前函数的执行结果已经从抛出异常 转变成 return true)。另外,在使用资源对象与流对象时,finally块必须对资源对象、流对象进行关闭。

Java异常体系结构

    Java异常体系的基类是Throwable,它主要有两个子类:Error Exception。其结构如下图:

      

    上图中,Error是指程序无法处理的错误,多指系统内部比较严重的错误。大多数这类错误与开发人员无关,我们关注的主要是Exception。

    Exception主要分为两块:运行时异常非运行时异常。RuntimeException及其子类都称为运行时异常;除此之外, 所有Exception的子类异常都是非运行时异常。

    运行时异常多指程序逻辑上出现问题(也就是我们自己写代码逻辑出了问题),常见的错误包括 ClassCastException:类型转换异常、NullPointerException:空指针异常、IndexOutOfBoundsException:越界异常...这些异常都可以通过程序逻辑处理来避免(比如加一个判断语句判断是否越界、是否属于某类型、是否为null),所以编译器把这些工作交给了程序员来把控,在编译期即使手动抛出了一个运行时异常不去捕获,编译器也会通过。因而这类异常也叫做"未检查异常"(uncheck)。同样属于未检查异常的还有所有的Error。即上图中,所有蓝色框表示未检查异常,橙色框表示"检查异常"(check)。对于检查异常,在可能发生异常的位置需要用try-catch块去捕获并处理,如果不处理它,就会一直向上层调用抛出,直到被处理为止。

throw 与 throws

    throws关键字主要在方法签名中使用,用于声明该方法可能抛出的异常。throws 可以理解成是一种通知行为,没有实际的抛出异常的动作,而仅仅是告诉调用他的上层函数,这里可能会抛出这个异常;

    throw用于在函数体内语句中,表示抛出一个实际的异常的实际动作,如果在函数内没有捕获并处理,那么将会一直向上抛出这个异常直到被main()/Thread.run()抛出。

    当一个函数throws声明函数可能抛出一个非运行时异常(检查异常)时,那么即使这个函数内部不显示使用throw,调用它的上层函数也必须包含处理这个异常的代码。举个例子:

public class Main {

public static void main(String[] args){

exceptionTest();
    }
    static int exceptionTest() throws IOException {
       
        return 0;   
    }
}   

上述代码中调用的exceptionTest函数声明抛出一个IOException属于检查异常,哪怕exceptionTest函数中不可能抛出这个异常,调用它的函数也必须对此异常做出捕获处理。现在main函数中没有相关的处理逻辑,所以会编译错误,如下图:

    而对运行时异常,就是另一种情况了:

public class Main {

 public static void main(String[] args){

 int i = divideTest(0);
 System.out.println(i);
 }
 static int divideTest(int b) throws ArithmeticException { 

 int i = 5/b;
 return i;
 }
 }

    同样在main函数没有处理异常的逻辑,这次声明抛出的异常是ArithmeicException,他属于运行时异常(RuntimeException),所以编译器对声明的抛出置之不理:

  

  虽然编译期通过,但在运行时程序仍然会自动抛出运行时异常,并一直向上抛出到Main函数。而Main()中没有对该异常的捕获处理,所以主线程终止。

    结论:我目前的理解是,throws一个运行时异常是没有任何实际意义的,除非你为了遵循某个统一的规范而这样做。throws 存在的意义主要是将可能的非运行时异常交给编译器把关,让编译器监督开发人员对这些异常进行捕获处理。

    另外,当你需要自定义一个异常时,如果需要在编译期检查,并在上层统一处理,那么直接继承Exception成为一个检查异常;如果不需要编译期检查,抛出异常表示程序异常需要直接中断,那么继承RuntimeException成为一个运行时异常即可。

希望本篇文章可以对各位朋友有所帮助!

(0)

相关推荐

  • java.net.MalformedURLException异常的解决方法

    java.net.MalformedURLException at java.net.URL.<init>(URL.java:619) at java.net.URL.<init>(URL.java:482) at java.net.URL.<init>(URL.java:431) 代码中URL url = new URL(someUrl);这一行出现java.net.MalformedURLException异常 解决方法是,对someUrl中的参数名和参数值都URL

  • Java异常继承结构解析_动力节点Java学院整理

    Java异常类层次结构图: 异常的英文单词是exception,字面翻译就是"意外.例外"的意思,也就是非正常情况.事实上,异常本质上是程序上的错误,包括程序逻辑错误和系统错误.比如使用空的引用.数组下标越界.内存溢出错误等,这些都是意外的情况,背离我们程序本身的意图.错误在我们编写程序的过程中会经常发生,包括编译期间和运行期间的错误,在编译期间出现的错误有编译器帮助我们一起修正,然而运行期间的错误便不是编译器力所能及了,并且运行期间的错误往往是难以预料的.假若程序在运行期间出现了错误

  • java异常(Exception)处理机制详解

    一. 异常的定义 在<Java编程思想>中这样定义 异常:阻止当前方法或作用域继续执行的问题.虽然java中有异常处理机制,但是要明确一点,决不应该用"正常"的态度来看待异常.绝对一点说异常就是某种意义上的错误,就是问题,它可能会导致程序失败.之所以java要提出异常处理机制,就是要告诉开发人员,你的程序出现了不正常的情况,请注意. 记得当初学习java的时候,异常总是搞不太清楚,不知道这个异常是什么意思,为什么会有这个机制?但是随着知识的积累逐渐也对异常有一点感觉了.举一

  • java中的connection reset 异常处理分析

    在Java中常看见的几个connection rest exception, Broken pipe, Connection reset,Connection reset by peer Socked reset case Linux中会有2个常见的sock reset 情况下的错误代码 ECONNRESET 该错误被描述为"connection reset by peer",即"对方复位连接",这种情况一般发生在服务进程较客户进程提前终止.当服务进程终止时会向客户

  • java基于spring注解AOP的异常处理的方法

    一.前言 项目刚刚开发的时候,并没有做好充足的准备.开发到一定程度的时候才会想到还有一些问题没有解决.就比如今天我要说的一个问题:异常的处理.写程序的时候一般都会通过try...catch...finally对异常进行处理,但是我们真的能在写程序的时候处理掉所有可能发生的异常吗? 以及发生异常的时候执行什么逻辑,返回什么提示信息,跳转到什么页面,这些都是要考虑到的. 二.基于@ControllerAdvice(加强的控制器)的异常处理 @ControllerAdvice注解内部使用@Except

  • Java中内存异常StackOverflowError与OutOfMemoryError详解

     Java中内存异常StackOverflowError与OutOfMemoryError详解 使用Java开发,经常回遇到内存异常的情况,而StackOverflowError和OutOfMemoryError便是最常遇见的错误. 首先,看看这两种错误的解释: 如果当前线程请求的栈深度大于虚拟机所允许的最大深度,将抛出StackOverflowError异常. 如果虚拟机在扩展栈时无法申请到足够的内存空间,则抛出OutOfMemoryError异常. 这里把异常分为两种情况,但是存在一些相互重

  • Java异常处理运行时异常(RuntimeException)详解及实例

      Java异常处理运行时异常(RuntimeException)详解及实例 RuntimeException RunntimeException的子类: ClassCastException 多态中,可以使用Instanceof 判断,进行规避 ArithmeticException 进行if判断,如果除数为0,进行return NullPointerException 进行if判断,是否为null ArrayIndexOutOfBoundsException 使用数组length属性,避免越

  • 深入理解java异常处理机制的原理和开发应用

    Java异常处理机制其最主要的几个关键字:try.catch.finally.throw.throws,以及各种各样的Exception.本篇文章主要在基础的使用方法上,介绍了如何更加合理的使用异常机制. try-catch-finally try-catch-finally块的用法比较简单,使用频次也最高.try块中包含可能出现异常的语句(当然这是人为决定的,try理论上可以包含任何代码),catch块负责捕获可能出现的异常,finally负责执行必须执行的语句,这里的代码不论是否发生了异常,

  • 深入理解java异常处理机制及应用

    1. 引子 try-catch-finally恐怕是大家再熟悉不过的语句了,而且感觉用起来也是很简单,逻辑上似乎也是很容易理解.不过,我亲自体验的"教训"告诉我,这个东西可不是想象中的那么简单.听话.不信?那你看看下面的代码,"猜猜"它执行后的结果会是什么?不要往后看答案.也不许执行代码看真正答案哦.如果你的答案是正确,那么这篇文章你就不用浪费时间看啦. package Test; public class TestException { public TestEx

  • Java异常处理机制深入理解

    目录 1.初识异常 2.异常的基本用法 异常处理流程 3.为什么要使用异常? 异常应只用于异常的情况 4. 异常的种类 4.1 受查异常 解决方案: 4.2非受查异常 5.如何使用异常 避免不必要的使用受查异常 6.自定义异常 1.初识异常 我们在写代码的时候都或多或少碰到了大大小小的异常,例如: public class Test { public static void main(String[] args) { int[] arr = {1,2,3}; System.out.println

  • Java异常处理机制try catch流程详解

    在项目中遇到try...catch...语句,因为对Java异常处理机制的流程不是很清楚,导致对相关逻辑代码不理解.所以现在来总结Java异常处理机制的处理流程: 1.异常处理的机制如下:在方法中用 try... catch... 语句捕获并处理异常,catch 语句可以有多个,用来匹配多个不同类型的异常.对于处理不了的异常或者要转型的异常,在方法的声明处通过 throws 声明异常,通过throw语句拋出异常,即由上层的调用方法来处理该异常. try { 逻辑程序块 } catch(Excep

  • JAVA异常处理机制之throws/throw使用情况的区别

    JAVA中throw和throws的区别:https://www.cnblogs.com/xiohao/p/3547443.html 区别:(摘自上面的博客) 1.throws出现在方法函数头:而throw出现在函数体. 2.throws表示出现异常的一种可能性,并不一定会发生这些异常:throw则是抛出了异常,执行throw则一定抛出了某种异常. 3.两者都是消极处理异常的方式(这里的消极并不是说这种方式不好),只是抛出或者可能抛出异常,但是不会由函数去处理异常,真正的处理异常由函数的上层调用

  • JAVA异常处理机制之throws/throw使用情况

    JAVA中throw和throws的区别:https://www.jb51.net/article/191065.htm 区别:(摘自上面的博客) 1.throws出现在方法函数头:而throw出现在函数体. 2.throws表示出现异常的一种可能性,并不一定会发生这些异常:throw则是抛出了异常,执行throw则一定抛出了某种异常. 3.两者都是消极处理异常的方式(这里的消极并不是说这种方式不好),只是抛出或者可能抛出异常,但是不会由函数去处理异常,真正的处理异常由函数的上层调用处理. 也就

  • Java序列化机制与原理的深入分析

    Java序列化算法透析 Serialization(序列化)是一种将对象以一连串的字节描述的过程:反序列化deserialization是一种将这些字节重建成一个对象的过程.Java序列化API提供一种处理对象序列化的标准机制.在这里你能学到如何序列化一个对象,什么时候需要序列化以及Java序列化的算法,我们用一个实例来示范序列化以后的字节是如何描述一个对象的信息的.序列化的必要性 Java中,一切都是对象,在分布式环境中经常需要将Object从这一端网络或设备传递到另一端.这就需要有一种可以在

  • java异常处理机制示例(java抛出异常、捕获、断言)

    这是一个介绍基本异常处理的小例子,包括抛出,捕获,断言,日志. Java异常处理通过5个关键字try.catch.throw.throws.finally进行管理.基本过程是用try语句块包住要监视的语句,如果在try语句块内出现异常,则异常会被抛出,你的代码在catch语句块中可以捕获到这个异常并做处理;还有以部分系统生成的异常在Java运行时自动抛出.你也可以通过throws关键字在方法上声明该方法要抛出异常,然后在方法内部通过throw抛出异常对象. 复制代码 代码如下: package

  • Java十分钟精通异常处理机制

    目录 异常处理机制的底层原理 异常的继承关系图 异常的处理 一.try-catch-finally结构 二.多catch处理不同的异常: 三.throws声明异常/throw抛出异常: 四.自定义异常: 五.常见的异常 异常处理机制的底层原理 抛出异常,在执行一个方法时,如果发送了异常,则这个方法生成代表该异常的一个对象,停止当前执行的 路径,并把异常提交给jre. 捕获异常:jre得到该异常后,虚招相应的代码来处理该异常.jre在方法的调用栈中查找,从生成异常的 方法开始回溯,直到找到相应的异

  • 浅析Java中的异常处理机制

    异常处理机制 1.抛出异常 2.捕获异常 3.异常处理五个关键字: try.catch.finally.throw.throws 注意:假设要捕获多个异常:需要按照层级关系(异常体系结构) 从小到大! package exception; /** * Java 捕获和抛出异常: * 异常处理机制 * 1.抛出异常 * 2.捕获异常 * 3.异常处理五个关键字 * try.catch.finally.throw.throws * 注意:假设要捕获多个异常:需要按照层级关系(异常体系结构) 从小到大

随机推荐