精华内容
参与话题
问答
  • java 异常分类和处理机制

    万次阅读 多人点赞 2018-06-01 15:08:26
    Java语言中的异常处理机制就解决的上述问题,把错误与异常的管理带到了面向对象的世界 Java语言定义了很多异常类,将运行错误和异常的信息和处理方法封装在了异常类中,帮助程序员检查和控制异常。即J.....

        一、背景介绍

           程序在运行过程中发生错误或异常情况是不可避免的,如果每一个运行时错误都由程序员手动控制和处理,其工作量是不可想象的。

          Java语言中的异常处理机制就解决的上述问题,把错误与异常的管理带到了面向对象的世界

     

     

    Java语言定义了很多异常类,将运行错误和异常的信息和处理方法封装在了异常类中,帮助程序员检查和控制异常。即Java造好了工具,程序员只要学会使用工具。

     

    二、java异常分类

    Java语言按照错误严重性,从throwale根类衍生出Error和Exception两大派系

    Error(错误)

    程序在执行过程中所遇到的硬件或操作系统的错误。错误对程序而言是致命的,将导致程序无法运行。常见的错误有内存溢出,jvm虚拟机自身的非正常运行,calss文件没有主方法。程序本生是不能处理错误的,只能依靠外界干预。Error是系统内部的错误,由jvm抛出,交给系统来处理。

         Exception(异常)

    是程序正常运行中,可以预料的意外情况。比如数据库连接中断,空指针,数组下标越界。异常出现可以导致程序非正常终止,也可以预先检测,被捕获处理掉,使程序继续运行。

     

    EXCEPTION(异常)按照性质,又分为编译异常(可检测)和运行时异常(不可检测)。

         编译时异常:

    又叫可检查异常,通常时由语法错和环境因素(外部资源)造成的异常。比如输入输出异常IOException,数据库操作SQLException。其特点是,Java语言强制要求捕获和处理所有非运行时异常。通过行为规范,强化程序的健壮性和安全性。

         运行时异常:

    又叫不检查异常RuntimeException,这些异常一般是由程序逻辑错误引起的,即语义错。比如算术异常,空指针异常NullPointerException,下标越界IndexOutOfBoundsException。运行时异常应该在程序测试期间被暴露出来,由程序员去调试,而避免捕获。

     

    所以,java语言处理运行时错误有三种方式,

    1. 一是程序不能处理的错误,
    2. 二是程序应该避免而可以不去捕获的运行时异常,
    3. 三是必须捕获的非运行时异常。

     

    三、java异常处理机制

    java默认处理机制:

    1抛出异常

    2终止程序

    异常处理程序机制:

    1抛出异常

    2try-catch-finally 捕获和处理异常

    当Java程序运行到某个方法发生异常时,产生一个对应异常类对象,包含异常事件类型,发生异常是应用程序的状态,和调用过程等信息,然后抛出,运行系统开始查找有没又匹配异常处理程序,么有,就中断程序,有就将控制权交个程序处理程序,处理异常。

    异常处理是程序开发中必不可少操作之一,但如何正确优雅的对异常进行处理确是一门学问,笔者在此处转载了一篇微博的内容,来谈一谈何对异常进行处理的。

    四、如何优雅的设计异常

    4.1 如何选择异常

    从开发经验来看,如果在一个应用中,需要开发一个方法(如某个功能的service方法),这个方法如果中间可能出现异常,那么你需要考虑这个异常出现之后是否调用者可以处理,并且你是否希望调用者进行处理,如果调用者可以处理,并且你也希望调用者进行处理,那么就要抛出受检异常,提醒调用者在使用你的方法时,考虑到如果抛出异常时如果进行处理,相似的,如果在写某个方法时,你认为这是个偶然异常,理论上说,你觉得运行时可能会碰到什么问题,而这些问题也许不是必然发生的,也不需要调用者显示的通过异常来判断业务流程操作的,那么这时就可以使用一个RuntimeException这样的非受检异常.

    4.2 什么时候才需要抛异常

    首先我们需要了解一个问题,什么时候才需要抛异常?异常的设计是方便给开发者使用的,但不是乱用的,笔者对于什么时候抛异常这个问题也问了很多朋友,能给出准确答案的确实不多。其实这个问题很简单,如果你觉得某些”问题”解决不了了,那么你就可以抛出异常了。比如,你在写一个service,其中在写到某段代码处,你发现可能会产生问题,那么就请抛出异常吧,相信我,你此时抛出异常将是一个最佳时机。

    4.3 应该抛出怎样的异常

    了解完了什么时候才需要抛出异常后,我们再思考一个问题,真的当我们抛出异常时,我们应该选用怎样的异常呢?究竟是受检异常还是非受检异常呢(RuntimeException)呢?我来举例说明一下这个问题,先从受检异常说起,比如说有这样一个业务逻辑,需要从某文件中读取某个数据,这个读取操作可能是由于文件被删除等其他问题导致无法获取从而出现读取错误,那么就要从redis或mysql数据库中再去获取此数据,参考如下代码,getKey(Integer)为入口程序.

     

    ok,看了以上代码以后,你也许心中有一些想法,原来受检异常可以控制义务逻辑,对,没错,通过受检异常真的可以控制业务逻辑,但是切记不要这样使用,我们应该合理的抛出异常,因为程序本身才是流程,异常的作用仅仅是当你进行不下去的时候找到的一个借口而已,它并不能当成控制程序流程的入口或出口,如果这样使用的话,是在将异常的作用扩大化,这样将会导致代码复杂程度的增加,耦合性会提高,代码可读性降低等问题。那么就一定不要使用这样的异常吗?其实也不是,在真的有这样的需求的时候,我们可以这样使用,只是切记,不要把它真的当成控制流程的工具或手段。那么究竟什么时候才要抛出这样的异常呢?要考虑,如果调用者调用出错后,一定要让调用者对此错误进行处理才可以,满足这样的要求时,我们才会考虑使用受检异常。
    接下来,我们来看一下非受检异常呢(RuntimeException),对于RuntimeException这种异常,我们其实很多见,比如java.lang.NullPointerException/java.lang.IllegalArgumentException等,那么这种异常我们时候抛出呢?当我们在写某个方法的时候,可能会偶然遇到某个错误,我们认为这个问题时运行时可能为发生的,并且理论上讲,没有这个问题的话,程序将会正常执行的时候,它不强制要求调用者一定要捕获这个异常,此时抛出RuntimeException异常,举个例子,当传来一个路径的时候,需要返回一个路径对应的File对象:

    上述例子表明,如果调用者调用getFiles(String)的时候如果path是空,那么就抛出空指针异常(它是RuntimeException的子类),调用者不用显示的进行try…catch…操作进行强制处理.这就要求调用者在调用这样的方法时先进行验证,避免发生RuntimeException.如下:

    4.4 应该选用哪种异常

    通过以上的描述和举例,可以总结出一个结论,RuntimeException异常和受检异常之间的区别就是:是否强制要求调用者必须处理此异常,如果强制要求调用者必须进行处理,那么就使用受检异常,否则就选择非受检异常(RuntimeException)。一般来讲,如果没有特殊的要求,我们建议使用RuntimeException异常。

    4.5 何优雅的设计java异常示例

    domain介绍

    根据项目场景来看,需要两个domain模型,一个是用户实体,一个是地址实体.
    Address domain如下:


     User domain如下:      

    ok,上边是一个模型关系,用户-收货地址的关系是1-n的关系。上边的@Data是使用了一个叫做lombok的工具,它自动生成了Setter和Getter等方法,用起来非常方便,感兴趣的读者可以自行了解一下。

    dao介绍

    数据连接层,我们使用了spring-data-jpa这个框架,它要求我们只需要继承框架提供的接口,并且按照约定对方法进行取名,就可以完成我们想要的数据库操作。
    用户数据库操作如下:

    收货地址操作如下:

    正如读者所看到的,我们的DAO只需要继承JpaRepository,它就已经帮我们完成了基本的CURD等操作,如果想了解更多关于spring-data的这个项目,请参考一下spring的官方文档,它比不方案我们对异常的研究。

    Service异常设计

    ok,终于到了我们的重点了,我们要完成service一些的部分操作:添加收货地址,删除收货地址,获取收货地址列表.
    首先看我的service接口定义:

    我们来关注一下实现:

    添加收货地址

    首先再来看一下之前整理的约束条件:

    入参:

    1. 用户id

    2. 收货地址实体信息

    约束:

    1. 用户id不能为空,且此用户确实是存在的

    2. 收货地址的必要字段不能为空

    3. 如果用户还没有收货地址,当此收货地址创建时设置成默认收货地址

    先看以下代码实现:

    其中,已经完成了上述所描述的三点约束条件,当三点约束条件都满足时,才可以进行正常的业务逻辑,否则将抛出异常(一般在此处建议抛出运行时异常-RuntimeException)。

    介绍以下以上我所用到的技术:

    1.Preconfitions.checkNotNull(T t)这个是使用Guava中的com.google.common.base.Preconditions进行判断的,因为service中用到的验证较多,所以建议将Preconfitions改成静态导入的方式:

    当然Guava的github中的说明也建议我们这样使用。

    2.BeanValidators.validateWithException(validator, address);
    这个使用了hibernate实现的jsr 303规范来做的,需要传入一个validator和一个需要验证的实体,那么validator是如何获取的呢,如下:

    他将获取一个Validator对象,然后我们在service中进行注入便可以使用了:

    那么BeanValidators这个类是如何实现的?其实实现方式很简单,只要去判断jsr 303的标注注解就ok了。
    那么jsr 303的注解写在哪里了呢?当然是写在address实体类中了:

    写好你需要的约束条件来进行判断,如果合理的话,才可以进行业务操作,从而对数据库进行操作。

    这块的验证是必须的,一个最主要的原因是:这样的验证可以避免脏数据的插入。如果读者有正式上线的经验的话,就可以理解这样的一个事情,任何的代码错误都可以容忍和修改,但是如果出现了脏数据问题,那么它有可能是一个毁灭性的灾难。程序的问题可以修改,但是脏数据的出现有可能无法恢复。所以这就是为什么在service中一定要判断好约束条件,再进行业务逻辑操作的原因了。

    此处的判断为业务逻辑判断,是从业务角度来进行筛选判断的,除此之外,有可能在很多场景中都会有不同的业务条件约束,只需要按照要求来做就好。

    对于约束条件的总结如下:

    1. 基本判断约束(null值等基本判断)

    2. 实体属性约束(满足jsr 303等基础判断)

    3. 业务条件约束(需求提出的不同的业务约束)

    当这个三点都满足时,才可以进行下一步操作

    ok,基本介绍了如何做一个基础的判断,那么再回到异常的设计问题上,上述代码已经很清楚的描述如何在适当的位置合理的判断一个异常了,那么如何合理的抛出异常呢?

    只抛出RuntimeException就算是优雅的抛出异常吗?当然不是,对于service中的抛出异常,笔者认为大致有两种抛出的方法:

    1. 抛出带状态码RumtimeException异常

    2. 抛出指定类型的RuntimeException异常

    相对这两种异常的方式进行结束,第一种异常指的是我所有的异常都抛RuntimeException异常,但是需要带一个状态码,调用者可以根据状态码再去查询究竟service抛出了一个什么样的异常。

     

    第二种异常是指在service中抛出什么样的异常就自定义一个指定的异常错误,然后在进行抛出异常。

    一般来讲,如果系统没有别的特殊需求的时候,在开发设计中,建议使用第二种方式。但是比如说像基础判断的异常,就可以完全使用guava给我们提供的类库进行操作。jsr 303异常也可以使用自己封装好的异常判断类进行操作,因为这两种异常都是属于基础判断,不需要为它们指定特殊的异常。但是对于第三点义务条件约束判断抛出的异常,就需要抛出指定类型的异常了。

    定义一个特定的异常类来进行这个义务异常的判断:

    然后将此处改为:

    ok,通过以上对service层的修改,代码更改如下:

     

     

     

    展开全文
  • 异常处理机制

    2015-03-07 08:20:44
    1. 引子  try…catch…finally恐怕是大家再熟悉不过的语句了,而且感觉用起来也是很简单,逻辑上似乎也是很容易理解。不过,我亲自体验的“教训”告诉我,这个东西可不是想象中的那么简单、听话。...

     1. 引子

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

    1. <span style="background-color: rgb(255, 255, 255);">package Test;  
    2.   
    3. public class TestException {  
    4.     public TestException() {  
    5.     }  
    6.   
    7.     boolean testEx() throws Exception {  
    8.         boolean ret = true;  
    9.         try {  
    10.             ret = testEx1();  
    11.         } catch (Exception e) {  
    12.             System.out.println("testEx, catch exception");  
    13.             ret = false;  
    14.             throw e;  
    15.         } finally {  
    16.             System.out.println("testEx, finally; return value=" + ret);  
    17.             return ret;  
    18.         }  
    19.     }  
    20.   
    21.     boolean testEx1() throws Exception {  
    22.         boolean ret = true;  
    23.         try {  
    24.             ret = testEx2();  
    25.             if (!ret) {  
    26.                 return false;  
    27.             }  
    28.             System.out.println("testEx1, at the end of try");  
    29.             return ret;  
    30.         } catch (Exception e) {  
    31.             System.out.println("testEx1, catch exception");  
    32.             ret = false;  
    33.             throw e;  
    34.         } finally {  
    35.             System.out.println("testEx1, finally; return value=" + ret);  
    36.             return ret;  
    37.         }  
    38.     }  
    39.   
    40.     boolean testEx2() throws Exception {  
    41.         boolean ret = true;  
    42.         try {  
    43.             int b = 12;  
    44.             int c;  
    45.             for (int i = 2; i >= -2; i--) {  
    46.                 c = b / i;  
    47.                 System.out.println("i=" + i);  
    48.             }  
    49.             return true;  
    50.         } catch (Exception e) {  
    51.             System.out.println("testEx2, catch exception");  
    52.             ret = false;  
    53.             throw e;  
    54.         } finally {  
    55.             System.out.println("testEx2, finally; return value=" + ret);  
    56.             return ret;  
    57.         }  
    58.     }  
    59.   
    60.     public static void main(String[] args) {  
    61.         TestException testException1 = new TestException();  
    62.         try {  
    63.             testException1.testEx();  
    64.         } catch (Exception e) {  
    65.             e.printStackTrace();  
    66.         }  
    67.     }  
    68. }  
    69. </span>  

    你的答案是什么?是下面的答案吗?

    i=2
    i=1
    testEx2, catch exception
    testEx2, finally; return value=false
    testEx1, catch exception
    testEx1, finally; return value=false
    testEx, catch exception
    testEx, finally; return value=false

    如果你的答案真的如上面所说,那么你错啦。^_^,那就建议你仔细看一看这篇文章或者拿上面的代码按各种不同的情况修改、执行、测试,你会发现有很多事情不是原来想象中的那么简单的。现在公布正确答案:

    i=2
    i=1
    testEx2, catch exception
    testEx2, finally; return value=false
    testEx1, finally; return value=false
    testEx, finally; return value=false


    注意说明:


    finally语句块不应该出现 应该出现return。上面的return ret最好是其他语句来处理相关逻辑。


     2.JAVA异常

       异常指不期而至的各种状况,如:文件找不到、网络连接失败、非法参数等。异常是一个事件,它发生在程序运行期间,干扰了正常的指令流程。Java通 过API中Throwable类的众多子类描述各种不同的异常。因而,Java异常都是对象,是Throwable子类的实例,描述了出现在一段编码中的 错误条件。当条件生成时,错误将引发异常。

          Java异常类层次结构图:


            


                                                                        图1 Java异常类层次结构图

       

            在 Java 中,所有的异常都有一个共同的祖先 Throwable(可抛出)。Throwable 指定代码中可用异常传播机制通过 Java 应用程序传输的任何问题的共性。
           Throwable: 有两个重要的子类:Exception(异常)和 Error(错误),二者都是 Java 异常处理的重要子类,各自都包含大量子类。

           Error(错误):是程序无法处理的错误,表示运行应用程序中较严重问题。大多数错误与代码编写者执行的操作无关,而表示代码运行时 JVM(Java 虚拟机)出现的问题。例如,Java虚拟机运行错误(Virtual MachineError),当 JVM 不再有继续执行操作所需的内存资源时,将出现 OutOfMemoryError。这些异常发生时,Java虚拟机(JVM)一般会选择线程终止。

    。这些错误表示故障发生于虚拟机自身、或者发生在虚拟机试图执行应用时,如Java虚拟机运行错误(Virtual MachineError)、类定义错误(NoClassDefFoundError)等。这些错误是不可查的,因为它们在应用程序的控制和处理能力之 外,而且绝大多数是程序运行时不允许出现的状况。对于设计合理的应用程序来说,即使确实发生了错误,本质上也不应该试图去处理它所引起的异常状况。在 Java中,错误通过Error的子类描述。

           Exception(异常):是程序本身可以处理的异常。

           Exception 类有一个重要的子类 RuntimeException。RuntimeException 类及其子类表示“JVM 常用操作”引发的错误。例如,若试图使用空值对象引用、除数为零或数组越界,则分别引发运行时异常(NullPointerException、ArithmeticException)和 ArrayIndexOutOfBoundException。

       注意:异常和错误的区别:异常能被程序本身可以处理,错误是无法处理。

       通常,Java的异常(包括Exception和Error)分为可查的异常(checked exceptions)和不可查的异常(unchecked exceptions)
          可查异常(编译器要求必须处置的异常):正确的程序在运行中,很容易出现的、情理可容的异常状况可查异常虽然是异常状况,但在一定程度上它的发生是可以预计的,而且一旦发生这种异常状况,就必须采取某种方式进行处理。

          除了RuntimeException及其子类以外,其他的Exception类及其子类都属于可查异常。这种异常的特点是Java编译器会检查它,也就是说,当程序中可能出现这类异常,要么用try-catch语句捕获它,要么用throws子句声明抛出它,否则编译不会通过。

         不可查异常(编译器不要求强制处置的异常):包括运行时异常(RuntimeException与其子类)和错误(Error)。

         Exception 这种异常分两大类运行时异常和非运行时异常(编译异常)。程序中应当尽可能去处理这些异常。

           运行时异常:都是RuntimeException类及其子类异常,如NullPointerException(空指针异常)、IndexOutOfBoundsException(下标越界异常)等,这些异常是不检查异常,程序中可以选择捕获处理,也可以不处理。这些异常一般是由程序逻辑错误引起的,程序应该从逻辑角度尽可能避免这类异常的发生。

          运行时异常的特点是Java编译器不会检查它,也就是说,当程序中可能出现这类异常,即使没有用try-catch语句捕获它,也没有用throws子句声明抛出它,也会编译通过。
           非运行时异常 (编译异常):是RuntimeException以外的异常,类型上都属于Exception类及其子类。从程序语法角度讲是必须进行处理的异常,如果不处理,程序就不能编译通过。如IOException、SQLException等以及用户自定义的Exception异常,一般情况下不自定义检查异常

        

     4.处理异常机制

            在 Java 应用程序中,异常处理机制为:抛出异常,捕捉异常。

            抛出异常当一个方法出现错误引发异常时,方法创建异常对象并交付运行时系统,异常对象中包含了异常类型和异常出现时的程序状态等异常信息。运行时系统负责寻找处置异常的代码并执行。

            捕获异常:在方法抛出异常之后,运行时系统将转为寻找合适的异常处理器(exception handler)。潜在的异常处理器是异常发生时依次存留在调用栈中的方法的集合。当异常处理器所能处理的异常类型与方法抛出的异常类型相符时,即为合适 的异常处理器。运行时系统从发生异常的方法开始,依次回查调用栈中的方法,直至找到含有合适异常处理器的方法并执行。当运行时系统遍历调用栈而未找到合适 的异常处理器,则运行时系统终止。同时,意味着Java程序的终止。

            对于运行时异常、错误或可查异常,Java技术所要求的异常处理方式有所不同。

            由于运行时异常的不可查性,为了更合理、更容易地实现应用程序,Java规定,运行时异常将由Java运行时系统自动抛出,允许应用程序忽略运行时异常。

           对于方法运行中可能出现的Error,当运行方法不欲捕捉时,Java允许该方法不做任何抛出声明。因为,大多数Error异常属于永远不能被允许发生的状况,也属于合理的应用程序不该捕捉的异常。

           对于所有的可查异常,Java规定:一个方法必须捕捉,或者声明抛出方法之外。也就是说,当一个方法选择不捕捉可查异常时,它必须声明将抛出异常。

            能够捕捉异常的方法,需要提供相符类型的异常处理器。所捕捉的异常,可能是由于自身语句所引发并抛出的异常,也可能是由某个调用的方法或者Java运行时 系统等抛出的异常。也就是说,一个方法所能捕捉的异常,一定是Java代码在某处所抛出的异常简单地说,异常总是先被抛出,后被捕捉的。

             任何Java代码都可以抛出异常,如:自己编写的代码、来自Java开发环境包中代码,或者Java运行时系统。无论是谁,都可以通过Java的throw语句抛出异常。

            从方法中抛出的任何异常都必须使用throws子句。

            捕捉异常通过try-catch语句或者try-catch-finally语句实现。

             总体来说,Java规定:对于可查异常必须捕捉、或者声明抛出。允许忽略不可查的RuntimeException和Error。

    4.1 捕获异常:try、catch 和 finally

    1.try-catch语句

         在Java中,异常通过try-catch语句捕获。其一般语法形式为:

    1. try {  
    2.     // 可能会发生异常的程序代码  
    3. catch (Type1 id1){  
    4.     // 捕获并处置try抛出的异常类型Type1  
    5. }  
    6. catch (Type2 id2){  
    7.      //捕获并处置try抛出的异常类型Type2  
    8. }  

           关键词try后的一对大括号将一块可能发生异常的代码包起来,称为监控区域。Java方法在运行过程中出现异常,则创建异常对象。将异常抛出监控区域之 外,由Java运行时系统试图寻找匹配的catch子句以捕获异常。若有匹配的catch子句,则运行其异常处理代码,try-catch语句结束。

           匹配的原则是:如果抛出的异常对象属于catch子句的异常类,或者属于该异常类的子类,则认为生成的异常对象与catch块捕获的异常类型相匹配。

    例1  捕捉throw语句抛出的“除数为0”异常。

    1. public class TestException {  
    2.     public static void main(String[] args) {  
    3.         int a = 6;  
    4.         int b = 0;  
    5.         try { // try监控区域  
    6.               
    7.             if (b == 0throw new ArithmeticException(); // 通过throw语句抛出异常  
    8.             System.out.println("a/b的值是:" + a / b);  
    9.         }  
    10.         catch (ArithmeticException e) { // catch捕捉异常  
    11.             System.out.println("程序出现异常,变量b不能为0。");  
    12.         }  
    13.         System.out.println("程序正常结束。");  
    14.     }  
    15. }  

    运行结果:程序出现异常,变量b不能为0。

                        程序正常结束。

            例1  在try监控区域通过if语句进行判断,当“除数为0”的错误条件成立时引发ArithmeticException异常,创建 ArithmeticException异常对象,并由throw语句将异常抛给Java运行时系统,由系统寻找匹配的异常处理器catch并运行相应异 常处理代码,打印输出“程序出现异常,变量b不能为0。”try-catch语句结束,继续程序流程。

            事实上,“除数为0”等ArithmeticException,是RuntimException的子类。而运行时异常将由运行时系统自动抛出,不需要使用throw语句。

    例2  捕捉运行时系统自动抛出“除数为0”引发的ArithmeticException异常。

    1.     public static void main(String[] args) {  
    2.         int a = 6;  
    3.         int b = 0;  
    4.         try {  
    5.             System.out.println("a/b的值是:" + a / b);  
    6.         } catch (ArithmeticException e) {  
    7.             System.out.println("程序出现异常,变量b不能为0。");  
    8.         }  
    9.         System.out.println("程序正常结束。");  
    10.     }  
    11. }  

    运行结果:程序出现异常,变量b不能为0。

                      程序正常结束。

    例2  中的语句:

    System.out.println("a/b的值是:" + a/b);

          在运行中出现“除数为0”错误,引发ArithmeticException异常。运行时系统创建异常对象并抛出监控区域,转而匹配合适的异常处理器catch,并执行相应的异常处理代码。

          由于检查运行时异常的代价远大于捕捉异常所带来的益处,运行时异常不可查。Java编译器允许忽略运行时异常,一个方法可以既不捕捉,也不声明抛出运行时异常。

    例3  不捕捉、也不声明抛出运行时异常。

    1. public class TestException {  
    2.     public static void main(String[] args) {  
    3.         int a, b;  
    4.         a = 6;  
    5.         b = 0// 除数b 的值为0  
    6.         System.out.println(a / b);  
    7.     }  
    8. }  

    运行结果:

    Exception in thread "main" java.lang.ArithmeticException: / by zero
    at Test.TestException.main(TestException.java:8)

    例4  程序可能存在除数为0异常和数组下标越界异常。

    1. public class TestException {  
    2.     public static void main(String[] args) {  
    3.         int[] intArray = new int[3];  
    4.         try {  
    5.             for (int i = 0; i <= intArray.length; i++) {  
    6.                 intArray[i] = i;  
    7.                 System.out.println("intArray[" + i + "] = " + intArray[i]);  
    8.                 System.out.println("intArray[" + i + "]模 " + (i - 2) + "的值:  "  
    9.                         + intArray[i] % (i - 2));  
    10.             }  
    11.         } catch (ArrayIndexOutOfBoundsException e) {  
    12.             System.out.println("intArray数组下标越界异常。");  
    13.         } catch (ArithmeticException e) {  
    14.             System.out.println("除数为0异常。");  
    15.         }  
    16.         System.out.println("程序正常结束。");  
    17.     }  
    18. }  

    运行结果:

    intArray[0] = 0

    intArray[0]模 -2的值:  0

    intArray[1] = 1

    intArray[1]模 -1的值:  0

    intArray[2] = 2

    除数为0异常。

    程序正常结束。

          例4  程序可能会出现除数为0异常,还可能会出现数组下标越界异常。程序运行过程中ArithmeticException异常类型是先行匹配的,因此执行相匹配的catch语句:

    1. catch (ArithmeticException e){  
    2.       System.out.println("除数为0异常。");  
    3.  }  

           需要注意的是,一旦某个catch捕获到匹配的异常类型,将进入异常处理代码。一经处理结束,就意味着整个try-catch语句结束。其他的catch子句不再有匹配和捕获异常类型的机会。

          Java通过异常类描述异常类型,异常类的层次结构如图1所示。对于有多个catch子句的异常程序而言,应该尽量将捕获底层异常类的catch子 句放在前面,同时尽量将捕获相对高层的异常类的catch子句放在后面。否则,捕获底层异常类的catch子句将可能会被屏蔽。

          RuntimeException异常类包括运行时各种常见的异常,ArithmeticException类和ArrayIndexOutOfBoundsException类都是它的子类。因此,RuntimeException异常类的catch子句应该放在 最后面,否则可能会屏蔽其后的特定异常处理或引起编译错误。

    2. try-catch-finally语句

          try-catch语句还可以包括第三部分,就是finally子句。它表示无论是否出现异常,都应当执行的内容。try-catch-finally语句的一般语法形式为:

    1.               try {  
    2.     // 可能会发生异常的程序代码  
    3. catch (Type1 id1) {  
    4.     // 捕获并处理try抛出的异常类型Type1  
    5. catch (Type2 id2) {  
    6.     // 捕获并处理try抛出的异常类型Type2  
    7. finally {  
    8.     // 无论是否发生异常,都将执行的语句块  
    9. }  

    例5  带finally子句的异常处理程序。

    1. public class TestException {  
    2.     public static void main(String args[]) {  
    3.         int i = 0;  
    4.         String greetings[] = { " Hello world !"" Hello World !! ",  
    5.                 " HELLO WORLD !!!" };  
    6.         while (i < 4) {  
    7.             try {  
    8.                 // 特别注意循环控制变量i的设计,避免造成无限循环  
    9.                 System.out.println(greetings[i++]);  
    10.             } catch (ArrayIndexOutOfBoundsException e) {  
    11.                 System.out.println("数组下标越界异常");  
    12.             } finally {  
    13.                 System.out.println("--------------------------");  
    14.             }  
    15.         }  
    16.     }  
    17. }  

    运行结果:

    Hello world !

    --------------------------

    Hello World !!

    --------------------------

    HELLO WORLD !!!

    --------------------------

    数组下标越界异常

    --------------------------

         在例5中,请特别注意try子句中语句块的设计,如果设计为如下,将会出现死循环。如果设计为:

    1. try {  
    2.       System.out.println (greetings[i]); i++;  
    3. }  


    小结:

    try 块:用于捕获异常。其后可接零个或多个catch块,如果没有catch块,则必须跟一个finally块。
    catch 块:用于处理try捕获到的异常。
    finally 块:无论是否捕获或处理异常,finally块里的语句都会被执行。
    当在try块或catch块中遇到return语句时,finally语句块将在方法返回之前被执行。在以下4种特殊情况下,finally块不会被执行:
    1)在finally语句块中发生了异常。
    2)在前面的代码中用了System.exit()退出程序。
    3)程序所在的线程死亡。
    4)关闭CPU。


    3. try-catch-finally 规则(异常处理语句的语法规则):

    1)  必须在 try 之后添加 catch 或 finally 块。try 块后可同时接 catch 和 finally 块,但至少有一个块。
    2) 必须遵循块顺序:若代码同时使用 catch 和 finally 块,则必须将 catch 块放在 try 块之后。
    3) catch 块与相应的异常类的类型相关。
    4) 一个 try 块可能有多个 catch 块。若如此,则执行第一个匹配块。即Java虚拟机会把实际抛出的异常对象依次和各个catch代码块声明的异常类型匹配,如果异常对象为某个异常类型或其子类的实例,就执行这个catch代码块,不会再执行其他的 catch代码块
    5) 可嵌套 try-catch-finally 结构。
    6) 在 try-catch-finally 结构中,可重新抛出异常。
    7) 除了下列情况,总将执行 finally 做为结束:JVM 过早终止(调用 System.exit(int));在 finally 块中抛出一个未处理的异常;计算机断电、失火、或遭遇病毒攻击。

    4. try、catch、finally语句块的执行顺序:

    1)当try没有捕获到异常时:try语句块中的语句逐一被执行,程序将跳过catch语句块,执行finally语句块和其后的语句;

    2)当try捕获到异常,catch语句块里没有处理此异常的情况:当try语句块里的某条语句出现异常时,而没有处理此异常的catch语句块时,此异常将会抛给JVM处理,finally语句块里的语句还是会被执行,但finally语句块后的语句不会被执行;

    3)当try捕获到异常,catch语句块里有处理此异常的情况:在try语句块中是按照顺序来执行的,当执行到某一条语句出现异常时,程序将跳到catch语句块,并与catch语句块逐一匹配,找到与之对应的处理程序,其他的catch语句块将不会被执行,而try语句块中,出现异常之后的语句也不会被执行,catch语句块执行完后,执行finally语句块里的语句,最后执行finally语句块后的语句;

     图示try、catch、finally语句块的执行:

                                              图2  图示try、catch、finally语句块的执行

    4.2 抛出异常

          任何Java代码都可以抛出异常,如:自己编写的代码、来自Java开发环境包中代码,或者Java运行时系统。无论是谁,都可以通过Java的throw语句抛出异常。从方法中抛出的任何异常都必须使用throws子句。

    1. throws抛出异常

       如果一个方法可能会出现异常,但没有能力处理这种异常,可以在方法声明处用throws子句来声明抛出异常。例如汽车在运行时可能会出现故障,汽车本身没办法处理这个故障,那就让开车的人来处理。

         throws语句用在方法定义时声明该方法要抛出的异常类型,如果抛出的是Exception异常类型,则该方法被声明为抛出所有的异常。多个异常可使用逗号分割。throws语句的语法格式为:

    1. methodname throws Exception1,Exception2,..,ExceptionN  
    2. {  
    3. }  

        方法名后的throws Exception1,Exception2,...,ExceptionN 为声明要抛出的异常列表。当方法抛出异常列表的异常时,方法将不对这些类型及其子类类型的异常作处理,而抛向调用该方法的方法,由他去处理。例如:

    1. import java.lang.Exception;  
    2. public class TestException {  
    3.     static void pop() throws NegativeArraySizeException {  
    4.         // 定义方法并抛出NegativeArraySizeException异常  
    5.         int[] arr = new int[-3]; // 创建数组  
    6.     }  
    7.   
    8.     public static void main(String[] args) { // 主方法  
    9.         try { // try语句处理异常信息  
    10.             pop(); // 调用pop()方法  
    11.         } catch (NegativeArraySizeException e) {  
    12.             System.out.println("pop()方法抛出的异常");// 输出异常信息  
    13.         }  
    14.     }  
    15.   
    16. }  

        使用throws关键字将异常抛给调用者后,如果调用者不想处理该异常,可以继续向上抛出,但最终要有能够处理该异常的调用者。

        pop方法没有处理异常NegativeArraySizeException,而是由main函数来处理。

        Throws抛出异常的规则:

        1) 如果是不可查异常(unchecked exception),即Error、RuntimeException或它们的子类,那么可以不使用throws关键字来声明要抛出的异常,编译仍能顺利通过,但在运行时会被系统抛出。

        2)必须声明方法可抛出的任何可查异常(checked exception)。即如果一个方法可能出现受可查异常,要么用try-catch语句捕获,要么用throws子句声明将它抛出,否则会导致编译错误

        3)仅当抛出了异常,该方法的调用者才必须处理或者重新抛出该异常。当方法的调用者无力处理该异常的时候,应该继续抛出,而不是囫囵吞枣。

        4)调用方法必须遵循任何可查异常的处理和声明规则。若覆盖一个方法,则不能声明与覆盖方法不同的异常。声明的任何异常必须是被覆盖方法所声明异常的同类或子类。

        例如:

    1. void method1() throws IOException{}  //合法    
    2.    
    3. //编译错误,必须捕获或声明抛出IOException    
    4. void method2(){    
    5.   method1();    
    6. }    
    7.    
    8. //合法,声明抛出IOException    
    9. void method3()throws IOException {    
    10.   method1();    
    11. }    
    12.    
    13. //合法,声明抛出Exception,IOException是Exception的子类    
    14. void method4()throws Exception {    
    15.   method1();    
    16. }    
    17.    
    18. //合法,捕获IOException    
    19. void method5(){    
    20.  try{    
    21.     method1();    
    22.  }catch(IOException e){…}    
    23. }    
    24.    
    25. //编译错误,必须捕获或声明抛出Exception    
    26. void method6(){    
    27.   try{    
    28.     method1();    
    29.   }catch(IOException e){throw new Exception();}    
    30. }    
    31.    
    32. //合法,声明抛出Exception    
    33. void method7()throws Exception{    
    34.  try{    
    35.   method1();    
    36.  }catch(IOException e){throw new Exception();}    
    37. }   
         判断一个方法可能会出现异常的依据如下:
         1)方法中有throw语句。例如,以上method7()方法的catch代码块有throw语句。
         2)调用了其他方法,其他方法用throws子句声明抛出某种异常。例如,method3()方法调用了method1()方法,method1()方法声明抛出IOException,因此,在method3()方法中可能会出现IOException。

    2. 使用throw抛出异常

       throw总是出现在函数体中,用来抛出一个Throwable类型的异常。程序会在throw语句后立即终止,它后面的语句执行不到,然后在包含它的所有try块中(可能在上层调用函数中)从里向外寻找含有与其匹配的catch子句的try块。
      我们知道,异常是异常类的实例对象,我们可以创建异常类的实例对象通过throw语句抛出。该语句的语法格式为:
        throw new exceptionname;
        例如抛出一个IOException类的异常对象:
        throw new IOException;
        要注意的是,throw 抛出的只能够是可抛出类Throwable 或者其子类的实例对象。下面的操作是错误的:
        throw new String("exception");

        这是因为String 不是Throwable 类的子类。

         如果抛出了检查异常,则还应该在方法头部声明方法可能抛出的异常类型。该方法的调用者也必须检查处理抛出的异常。

           如果所有方法都层层上抛获取的异常,最终JVM会进行处理,处理也很简单,就是打印异常消息和堆栈信息。如果抛出的是Error或RuntimeException,则该方法的调用者可选择处理该异常。

    1. package Test;  
    2. import java.lang.Exception;  
    3. public class TestException {  
    4.     static int quotient(int x, int y) throws MyException { // 定义方法抛出异常  
    5.         if (y < 0) { // 判断参数是否小于0  
    6.             throw new MyException("除数不能是负数"); // 异常信息  
    7.         }  
    8.         return x/y; // 返回值  
    9.     }  
    10.     public static void main(String args[]) { // 主方法  
    11.         int  a =3;  
    12.         int  b =0;   
    13.         try { // try语句包含可能发生异常的语句  
    14.             int result = quotient(a, b); // 调用方法quotient()  
    15.         } catch (MyException e) { // 处理自定义异常  
    16.             System.out.println(e.getMessage()); // 输出异常信息  
    17.         } catch (ArithmeticException e) { // 处理ArithmeticException异常  
    18.             System.out.println("除数不能为0"); // 输出提示信息  
    19.         } catch (Exception e) { // 处理其他异常  
    20.             System.out.println("程序发生了其他的异常"); // 输出提示信息  
    21.         }  
    22.     }  
    23.   
    24. }  
    25. class MyException extends Exception { // 创建自定义异常类  
    26.     String message; // 定义String类型变量  
    27.     public MyException(String ErrorMessagr) { // 父类方法  
    28.         message = ErrorMessagr;  
    29.     }  
    30.   
    31.     public String getMessage() { // 覆盖getMessage()方法  
    32.         return message;  
    33.     }  
    34. }  

    4.3 异常链

          1) 如果调用quotient(3,-1),将发生MyException异常,程序调转到catch (MyException e)代码块中执行;

          2) 如果调用quotient(5,0),将会因“除数为0”错误引发ArithmeticException异常,属于运行时异常类,由Java运行时系统自动抛出。quotient()方法没有捕捉ArithmeticException异常,Java运行时系统将沿方法调用栈查到main方法,将抛出的异常上传至quotient()方法的调用者:

             int result = quotient(a, b); // 调用方法quotient()
            由于该语句在try监控区域内,因此传回的“除数为0”的ArithmeticException异常由Java运行时系统抛出,并匹配catch子句:

           catch (ArithmeticException e) { // 处理ArithmeticException异常
    System.out.println("除数不能为0"); // 输出提示信息

            处理结果是输出“除数不能为0”。Java这种向上传递异常信息的处理机制,形成异常链

           Java方法抛出的可查异常将依据调用栈、沿着方法调用的层次结构一直传递到具备处理能力的调用方法,最高层次到main方法为止。如果异常传递到main方法,而main不具备处理能力,也没有通过throws声明抛出该异常,将可能出现编译错误。

          3)如还有其他异常发生,将使用catch (Exception e)捕捉异常。由于Exception是所有异常类的父类,如果将catch (Exception e)代码块放在其他两个代码块的前面,后面的代码块将永远得不到执行,就没有什么意义了,所以catch语句的顺序不可掉换。

    4.4 Throwable类中的常用方法

    注意:catch关键字后面括号中的Exception类型的参数e。Exception就是try代码块传递给catch代码块的变量类型,e就是变量名。catch代码块中语句"e.getMessage();"用于输出错误性质。通常异常处理常用3个函数来获取异常的有关信息:

         getCause():返回抛出异常的原因。如果 cause 不存在或未知,则返回 null。

      getMeage():返回异常的消息信息。

      printStackTrace():对象的堆栈跟踪输出至错误输出流,作为字段 System.err 的值。

         有时为了简单会忽略掉catch语句后的代码,这样try-catch语句就成了一种摆设,一旦程序在运行过程中出现了异常,就会忽略处理异常,而错误发生的原因很难查找。


     5.Java常见异常

      

    在Java中提供了一些异常用来描述经常发生的错误,对于这些异常,有的需要程序员进行捕获处理或声明抛出,有的是由Java虚拟机自动进行捕获处理。Java中常见的异常类:

    1. runtimeException子类:

        1、 java.lang.ArrayIndexOutOfBoundsException
        数组索引越界异常。当对数组的索引值为负数或大于等于数组大小时抛出。
        2、java.lang.ArithmeticException
        算术条件异常。譬如:整数除零等。
        3、java.lang.NullPointerException
        空指针异常。当应用试图在要求使用对象的地方使用了null时,抛出该异常。譬如:调用null对象的实例方法、访问null对象的属性、计算null对象的长度、使用throw语句抛出null等等
        4、java.lang.ClassNotFoundException
        找不到类异常。当应用试图根据字符串形式的类名构造类,而在遍历CLASSPAH之后找不到对应名称的class文件时,抛出该异常。

       5、java.lang.NegativeArraySizeException  数组长度为负异常

       6、java.lang.ArrayStoreException 数组中包含不兼容的值抛出的异常

       7、java.lang.SecurityException 安全性异常

       8、java.lang.IllegalArgumentException 非法参数异常

    2.IOException

    IOException:操作输入流和输出流时可能出现的异常。

    EOFException   文件已结束异常

    FileNotFoundException   文件未找到异常

    3. 其他

    ClassCastException    类型转换异常类

    ArrayStoreException  数组中包含不兼容的值抛出的异常

    SQLException   操作数据库异常类

    NoSuchFieldException   字段未找到异常

    NoSuchMethodException   方法未找到抛出的异常

    NumberFormatException    字符串转换为数字抛出的异常

    StringIndexOutOfBoundsException 字符串索引超出范围抛出的异常

    IllegalAccessException  不允许访问某类异常

    InstantiationException  当应用程序试图使用Class类中的newInstance()方法创建一个类的实例,而指定的类对象无法被实例化时,抛出该异常

        

     6.自定义异常

    使用Java内置的异常类可以描述在编程时出现的大部分异常情况。除此之外,用户还可以自定义异常。用户自定义异常类,只需继承Exception类即可。
        在程序中使用自定义异常类,大体可分为以下几个步骤。
    (1)创建自定义异常类。
    (2)在方法中通过throw关键字抛出异常对象。
    (3)如果在当前抛出异常的方法中处理异常,可以使用try-catch语句捕获并处理;否则在方法的声明处通过throws关键字指明要抛出给方法调用者的异常,继续进行下一步操作。
    (4)在出现异常方法的调用者中捕获并处理异常。

    在上面的“使用throw抛出异常”例子已经提到了。





    展开全文
  • java中的异常处理机制

    千次阅读 2018-11-13 10:00:49
    增加了异常处理机制后的程序有更好的容错性。 异常处理机制 java的异常处理机制可以让程序员具有极好的容错性,让程序更加健壮。当程序运行出现意外情形时,系统会自动生成一个Expection对象来通知程序,从而...

    异常概述
    异常处理已经成为衡量一门语言是否标准的标准之一。增加了异常处理机制后的程序有更好的容错性。


    异常处理机制

    java的异常处理机制可以让程序员具有极好的容错性,让程序更加健壮。当程序运行出现意外情形时,系统会自动生成一个Expection对象来通知程序,从而实现将“业务功能实现代码”和“错误处理代码”分离,提供更好的可读性。

    使用try…catch捕获异常
    语法结构

    try{
    	//业务实现代码
    	...
    }
    catch(Exception e){
    	alert输入不合法
    }
    

    当try块里的业务逻辑代码出现异常时,系统会自动生成一个异常对象,该异常对象被提交给java运行时环境,这个过程被称为抛出异常
    当运行时环境收到异常对象时,会寻找能处理该异常对象的catch块,如果找到合适的catch块,则把该异常对象交给该catch快处理,这个过程被称为捕获异常;如果java运行时环境找不到捕获异常的catch块,则运行时环境终止,java程序也将退出。

    运行下面的程序,报出异常ArithmeticException: / by zero,除数不能为0

        public static void main(String[] args) {
            int a=1;
            int b=0;
            System.out.println(1/0);
            //Exception in thread "main" java.lang.ArithmeticException: / by zero
        }
    

    用try…catch捕获这个异常,友好的处理。

        public static void main(String[] args) {
            int a=1;
            int b=0;
            try {
                System.out.println(1/0);
            }catch (ArithmeticException e){
                System.out.println("除数不能为0");
                //除数不能为0
            }
        }
    

    异常类的继承体系

    当java运行时环境收到异常后,会依次判断该异常对象是否是catch块后异常类或其子类的实例,如果是,java运行时环境将调用该catch块来处理异常;否则再次拿该异常对象和下一个catch块里的异常类进行比较。

    在这里插入图片描述

    当程序进入负责异常处理的catch块时,系统生成的异常对象ex将会传给catch后的异常参数。try后面可以跟catch块,当系统发生不同的异常情况时,系统会生成不同的ex对象。在通常情况下如果try块被执行一次,则try后只有一个catch块被执行,除非使用continue,否则不会执行多个catch块。

    java中异常类的继承

    java把所有非正常情况分为两种:异常(Exception)和错误(Error),都集成Throwable父类。
    在这里插入图片描述

    Error错误,一般是指与虚拟机相关的问题,这种错误无法恢复或不可能捕获,将导致应用程序中断。
    处理异常规则:先处理小异常,再处理大异常

    java7提供的多异常捕获
    从java7开始一个catch块可以捕获多种类型的异常。
    规则简述:

    • 捕获多种类型的异常时,多种异常类型之间用"|"隔开;
    • 捕获多类型的异常时,异常变量之间有隐式的final修饰,因此程序不能对异常变量重新赋值。
        public static void main(String[] args) {
            try {
                int a=Integer.parseInt(args[0]);
                int b=Integer.parseInt(args[1]);
                int c=a/b;
                System.out.println(c);
            }catch (IndexOutOfBoundsException|NumberFormatException|ArithmeticException ie){
                //异常变量默认有final修饰
                System.out.println("程序发生了数组越界、数字格式异常、算数异常之一");
            }catch (Exception e){
                System.out.println("未知异常");
            }
        }
    

    访问异常信息

    如果程序需要在catch块中访问异常对象的相关信息,则可以通过访问catch块后的异常形参来获得。当决定调用某个catch块来处理该异常时,会将异常对象赋值给异常数。
    异常对象包含的常用方法:

    • getMessage():返回该异常的详细描述字符;
    • printStackTrace():将该异常对象的跟踪栈信息输出到标准错误输出;
    • printStackTrace(PrintStream s):将该异常的跟踪栈信息输出带指定输出流;
    • getStackTrace():返回该异常的跟踪栈信息。
        public static void main(String[] args) {
            try {
                FileInputStream fis = new FileInputStream("a.txt");
            }catch (IOException ioe){
                System.out.println(ioe.getMessage());
                ioe.printStackTrace();
            }
    
        }
    

    在这里插入图片描述

    使用finally回收资源

    有些时候,程序在try块里打开一些物理资源(如:数据库连接,网络连接,磁盘文件),这些物理资源都必须显式的回收。
    为了保证一定能回收try块中打开的物理资源,异常处理机制提供了finally块。不管try块中的代码是否出现异常,也不管哪一个catch块被执行,甚至在try和catch快中执行了return语句,finally块总会被执行。

    异常处理语法中只有try块是必须的,catch块和finally块是可选的,两者可以同时出>现,也可以只出现一个,但不能都没有。

        public static void main(String[] args) {
            FileInputStream fis=null;
            try {
                fis = new FileInputStream("a.txt");
            }catch (IOException ioe){
                System.out.println(ioe.getMessage());//a.txt (系统找不到指定的文件。)
                return; //强制方法返回
                //System.exit(1);//退出虚拟机
            }finally {
                if(fis!=null){
                    try {
                        fis.close();
                    }catch (IOException ioe){
                        ioe.printStackTrace();
                    }
                }
                System.out.println("执行finally块里的资源回收");//执行finally块里的资源回收
            }
        }
    

    在这里插入图片描述
    上面的方法中即使执行了return还是可以看到finally块中的代码被执行。
    但是如果将return注释,而将System.exit(1)打开注释会看到虚拟机直接退出,finally块没有被执行。
    注意
    如果执行try或catch块遇到return,方法不会直接退出,而是去找是否有finally块,如果有先执行finally块,再返回执行try或catch中的return。如果finally块里还有return则会直接结束方法,就不会返回到try护catch执行return。所以尽量避免finally块里使用return或throw等导致方法终止的语句,否则会出现一些奇怪的情况。

    java7的自动关闭资源的try语句

    在前面程序看到当程序使用finally块关闭资源时,程序显得异常臃肿;
    java7的出现改变了这种局面,增强了try语句的功能,它允许在try关键字后紧跟一对圆括号,圆括号可以声明、初始化一个或多个资源,此处的资源是指那些在程序结束时显式关闭的资源。
    为了保证try语句可以正常的关闭资源,这些资源实现类必须实现AutoCloseable或Closeable接口。

        public static void main(String[] args) throws IOException {
            try (
                    BufferedReader bufferedReader = new BufferedReader(new FileReader("a.txt"));
                    PrintStream printStream = new PrintStream(new FileOutputStream("b.txt"));
                    ){
                System.out.println(bufferedReader.readLine());
                printStream.println("庄生晓梦迷蝴蝶");
            }
    
        }
    

    自动关闭资源的try语句相当于包含了隐式的finally块。

    Checked异常和Runtime异常体系

    Java的异常被分为两大类:Checked(编译时)异常和Runtime(运行时)异常。所有的RuntimeException类及子类的实例被称为Runtime异常;不是RuntimeException类及子类的异常则被称为Checked异常。
    对于Checked异常处理的方式有两种:

    • 当前方法明确知道如何处理异常,程序应该使用try…catch块来捕获该异常,然后在对应的catch块中修复该异常。
    • 当前方法不知道如何处理这种异常,应该在定义该方法时声明抛出该异常。

    使用throws声明抛出异常

    使用throws声明抛出异常的思路是,当前方法不知道如何处理这种类型的异常,该异常应该由上一级调用者处理;如果main方法也不知道如何处理,则抛给JVM处理。JVM对异常的处理方法是打印跟踪栈信息,并中止程序运行。
    throws声明抛出只能在方法签名中使用,throws可以声明抛出多个异常类,由逗号隔开。一旦抛出该异常,就不用使用try…catch来捕获了。

    使用throws声明抛出异常有一个限制:子类方法声明抛出的异常类型应该是父类方法声明抛出的异常类型的子类或相同,子类方法声明抛出的异常不允许比父类方法声明抛出的异常多。

    使用Checked存在的不便之处:

    • 对于程序中的Checked异常,java要求必须显式捕获并处理该异常,或者显式声明抛出该异常,这样增加了编程复杂度;
    • 如果在方法显式声明抛出Checked异常,将会导致方法签名与异常耦合,如果该方法重写了父类的方法,则抛出的异常还会受到被重写方法所抛出异常的限制。

    使用throw抛出异常

    抛出异常

    当程序出现错误时,系统会自动抛出异常;除此之外,java也允许程序自行抛出异常,自行抛出异常用throw语句来完成注意不是前面的throws,两者有区别。
    如果需要在程序中自行抛出异常,则应使用throw语句,throw语句可以单独使用,throw语句抛出的不是异常类,而是一个异常实例,而且每次只能抛出一次异常实例。
    不管是系统自动抛出的异常还是程序员手动抛出的异常,java运行时环境对异常的处理没有任何差别。

        public static void main(String[] args) throws Exception {
            //输入字符串长度不超过5,否则引发异常
            Scanner sc = new Scanner(System.in);
            System.out.print("请输入长度不超过5的字符串:");
            String s=sc.next();
            if(s.length()<5){
                System.out.println(s);
            }else {
                throw new Exception("字符串长度超度5");
            }
        }
    

    在这里插入图片描述

    如果throw语句抛出的异常是Checked异常,则该throw语句要么处于try显式捕获异常,要么放在一个带throws声明抛出的方法中;如果throw语句抛出的异常时Runtime异常,则该语句无需放在try块里,也无需放在throws声明抛出的方法中,程序既可以显式的捕获异常,也可以完全不理会该异常。

        public static void main(String[] args) {
            try {
                throwChecked(3);
            }catch (Exception e){
                System.out.println(e.getMessage());
            }
            throwRuntime(3);
        }
    
    
        public static void throwChecked(int i) throws Exception {
            if(i>0){
                //自行抛出Exception异常
                throw new Exception("a的值大于0,不符合要求");
            }
        }
        public static void throwRuntime(int i){
            if(i>0){
                //自行抛出RuntimeException异常,既可以显式捕获,也可以完全不理会,把异常交给该方法的调用者处理
                throw new RuntimeException("a的值大于0,不符合要求");
            }
        }
    

    自定义异常类

    用户自定义异常类都应该继承Exception基类,如果希望自定义Runtime异常,则应该继承RuntimeException基类。定义异常类时需要两个构造器:一个是无参构造;另一个是带一个字符串参数的构造器,这个字符串将作为该异常对象的描述信息。

    public class DefineException extends Exception {
        //无参构造器
        public DefineException(){};
        //带一个字符串参数的构造器
        public DefineException(String str){
            super(str);
        }
    }
    

    如果需要自定义Runtime异常,只需将继承父类Exception改成RuntimeException即可。

    catch和throw同时使用

    在实际生活中需要更复杂的处理方法,在异常出现的当前方法中,程序只对异常进行部分处理,还有些处理需要在该方法的调用者中才能完成,所以再次抛出异常,让该方法的调用者也能捕获到该异常。

    下面的程序中,bid()方法不仅try…catch了异常,而且throws抛出了异常,这样main方法(bid方法的调用者)也可以处理该异常,并将该异常的详细描述信息输出到标准错误输出。

    package org.westos.demo8;
    
    public class ExceptionDemo6 {
        private double iniePrice=30.0;
        public  void bid(String bidPrice) throws DefineException {
            double d=0.0;
            try {
                 d = Double.parseDouble(bidPrice);
            }catch (Exception e){
                //此处完成本方法中可以对异常执行的修复处理
                //此处仅仅是在控制台打印异常的跟踪信息
                e.printStackTrace();
                //再次抛出自定义异常
                throw new DefineException("竞拍价必须是数值,不能包含其他字符");
            }
            if(iniePrice>d){
                throw new DefineException("竞拍价比起拍价低,不运行竞拍");
            }
            iniePrice=d;
        }
    
        public static void main(String[] args) {
            ExceptionDemo6 ex = new ExceptionDemo6();
            try {
                ex.bid("df");
            }catch (DefineException de){
                //再次捕获到bid方法中的异常,并对该异常进行处理
                System.out.println(de.getMessage());
            }
    
        }
    }
    
    

    java7增强的throw语句
    在java7之前,像下面的程序,匹配到的异常是Exception,则抛出的异常也是Exception,但是在java7之后编译器会检查throw语句抛出异常的实际类型,所以抛出具体异常 FileNotFoundException。

        public static void main(String[] args) throws FileNotFoundException {
            try {
                new FileOutputStream("a.txt");
            }catch (Exception e){
                e.printStackTrace();
                throw e;
            }
        }
    

    异常链

    对于真正的企业级应用而言,常常有严格的分层关系,层与层之间有非常清晰地划分,上层功能的实现严格依赖下层的API,也不会跨层访问。
    在这里插入图片描述

    当业务逻辑访问持久层出现SQLException异常时,程序不应该把底层的SQLException异常传到用户界面。原因如下:

    • SQLException异常对用户而言毫无帮助;
    • 异常会暴露隐私安全信息;

    把底层异常暴露给用户是不负责任的表现,通常的做法是:程序先捕获异常,然后抛出一个新的业务异常,新的业务异常包含了对用户的提示信息,这种处理方式称为异常转译
    这种把原始信息隐藏起来,仅向上提供必要的异常提示信息的处理方式,可以保证底层异常不会扩散到表现层,避免向上暴露太多实现细节。这种把捕获一个异常然后接着抛出另一个异常,并把原始异常信息保存下来是一种典型的链式处理,也被称为异常链
    从java1.4之后所有Throwable的子类在构造器中都可以接受一个cause对象作为参数。这个cause就用来表示原始异常,这样可以把原始异常传递给新的异常,使得即使在当前位置创建并抛出新的异常,你也能通过这个异常链追踪到异常最初发生的位置。

    异常处理规则

    成功的异常处理应该实现如下4个目标:

    • 使程序代码混乱最小化;
    • 捕获并保留诊断信息;
    • 通知合适的人员;
    • 采用合适的方式结束异常活动。

    不要过度使用异常
    主要体现在两个方面:

    • 把异常和普通错误混淆在一起,不再写任何错误处理代码,而是以简单地抛出异常来代替所有错误处理;
    • 使用异常来代替流程控制。
      异常处理机制的初衷是将不可预期异常的处理代码和正常的业务逻辑处理代码分离,因此绝不要使用异常处理来替换正常的业务逻辑判断

    不要使用过于庞大的try块

    因为try块里的代码过于庞大,业务过于复杂,就会造成try块中出现异常的可能性大大增加,从而导致分析异常原因的难度也增加。正确的做法是把大块的try块分割成多个可能出现异常的程序段落,并把它们放在单独的try块中,分别捕获异常并处理。

    避免使用Catch All语句
    Catch All语句是指一种异常捕获模块,它可以处理程序发生的所有可能异常。
    这种处理方式的不足之处:

    • 所有异常都采用相同的处理方式,这将导致无法对不同的异常分情况处理,如果要分就得在catch块中使用分支语句,这是得不偿失的。
    • 这种捕获方式可能将程序中的错误、Runtime异常等可能导致程序终止的情况全部捕获到,从而压制了异常。

    不要忽略捕获到的异常

    既然捕获到了异常,就要进行处理,否则程序除了错误所有人看不到任何异常。
    应采取适当措施:

    • 处理异常,对异常进行合适的修复,然后绕过异常发生的地方继续执行。
    • 重新抛出异常,把当前运行环境下能做的事情尽量做完,然后进行异常转译,把异常包装成当前层的异常,重新抛出给上层调用者。
    • 在合适的层处理异常。
    展开全文
  • Java异常处理机制

    2020-11-20 22:00:54
    Java异常处理机制 什么是异常 运行时发生的错误称为异常。处理这些异常就称为异常处理。 一旦引发异常,程序将突然中止,且控制将返回操作系统。 发生异常后此前分配的所有资源都将保留在相同的状态,这将导致资源...

    Java异常处理机制

    什么是异常

    • 运行时发生的错误称为异常。处理这些异常就称为异常处理。
    • 一旦引发异常,程序将突然中止,且控制将返回操作系统。
    • 发生异常后此前分配的所有资源都将保留在相同的状态,这将导致资源漏洞。

    Java异常处理基础

    Java异常处理机制采用一个统一和相对简单的抛出和处理错误的机制。如果一个方法本身能引发异常,当所调用的方法出现异常时,调用者可以捕获异常使之得到处理;也可以回避异常,这时异常将在调用的堆栈中向下传递,直到被处理。

    在这里插入图片描述

    常见异常及其用途

    在这里插入图片描述

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    异常处理机制

    Java异常机制用到的几个关键字:try、catch、finally、throw、throws

    • try – 用于监听。将要被监听的代码(可能抛出异常的代码)放在try语句块之内,当try语句块内发生异常时,异常就被抛出。
    • catch – 用于捕获异常。catch用来捕获try语句块中发生的异常。
    • finally – finally语句块总是会被执行。它主要用于回收在try块里打开的物力资源(如数据库连接、网络连接和磁盘文件)。只有finally块,执行完成之后,才会回来执行try或者catch块中的return或者throw语句,如果finally中使用了return或者throw等终止方法的语句,则就不会跳回执行,直接停止。
    • throw – 用于抛出异常。
    • throws – 用在方法签名中,用于声明该方法可能抛出的异常。主方法上也可以使用throws抛出。如果在主方法上使用了throws抛出,就表示在主方法里面可以不用强制性进行异常处理,如果出现了异常,就交给JVM进行默认处理,则此时会导致程序中断执行。

    1.捕获异常:
    try-catch语句
    语法格式:

     try {  
          // 可能会发生异常的程序代码  
     } catch (Type1 id1){  
          // 捕获并处置try抛出的异常类型Type1  
     } catch (Type2 id2){  
            //捕获并处置try抛出的异常类型Type2  
     } 
    

    try-catch-finally语句
    语法格式:

    try {  
           // 可能会发生异常的程序代码  
    } catch (Type1 id1) {  
            // 捕获并处理try抛出的异常类型Type1  
    } catch (Type2 id2) {  
            // 捕获并处理try抛出的异常类型Type2  
    } finally {  
             // 无论是否发生异常,都将执行的语句块  
    }
    

    例子:

    package lesson_4;
    public class lession_1 {
    
    	public static void main(String[] args) {
    		
    		try {
    			int x= Integer.parseInt(args[0]);
    			int y= Integer.parseInt(args[1]);//从命令行获取数据
    			int z;
    			
    			z=x/y;
    			System.out.println(x+"/"+y+"="+z);
    		//这些异常都是运行时异常	
    		}catch(ArrayIndexOutOfBoundsException e) {
    			System.out.println("你没有输入数据");
    		}catch(NumberFormatException e) {
    			System.out.println("你输入的不是数字");
    		}catch(ArithmeticException e) {
    			System.out.println("除数不能为0!");
    		}catch(Exception e) {
    			System.out.println("程序异常");
    		}finally {
    			System.out.println("我始终被执行,通常用来做清洗工作!");
    		}
    	}
    }
    

    ③try-finally语句
    语法格式:

    try {  
         // 可能会发生异常的程序代码   
    } finally {  
         // 无论是否发生异常,都将执行的语句块  
    }
    
    

    例子:

    package lesson_4;
    public class lession_1 {
    
    	public static void main(String[] args) {
    		
    		try {
    			int x= Integer.parseInt(args[0]);
    			int y= Integer.parseInt(args[1]);//从命令行获取数据
    			int z;
    			
    			z=x/y;
    			System.out.println(x+"/"+y+"="+z);
    		}finally {
    			//释放资源
    			System.out.println("我始终被执行,通常用来做清洗工作!");
    		}
    	}
    
    }
    
    • try – 用于监听。将要被监听的代码(可能抛出异常的代码)放在try语句块之内,当try语句块内发生异常时,异常就被抛出。
    • catch – 用于捕获异常,catch用来捕获try语句块中发生的异常
    • finally – finally语句块总是会被执行,它主要用于回收在try块里打开的物力资源(如数据库连接、网络连接和磁盘文件)。当在try块或catch块中遇到return语句时,finally语句块将在方法返回之前被执行。

    final和finally的区别

    final:
    ①final修饰的类是不能被继承的,因为其是一个最终类;
    ②final修饰的变量是一个常量,只能被赋值一次;
    ③final修饰的方法也不能重写,但能被重载;
    ④final是一个修饰符,可以修饰类、方法、变量;
    ⑤内部类只能访问被final修饰的局部变量。

    finally:
    ①finally 关键字用来创建在 try 代码块后面执行的代码块。
    ②无论是否发生异常,finally 代码块中的代码总会被执行。
    ③在 finally 代码块中,可以运行清理类型等收尾善后性质的语句。
    ④finally 代码块出现在 catch 代码块最后。

    2.抛出异常
    throws:通常被用在声明方法时,用来指定方法可能抛出的异常,多个异常可使用逗号分隔。throws关键字将异常抛给上一级,如果不想处理该异常,可以继续向上抛出,但最终要有能够处理该异常的代码。

    throw:通常用在方法体中或者用来抛出用户自定义异常,并且抛出一个异常对象。程序在执行到throw语句时立即停止,如果要捕捉throw抛出的异常,则必须使用try-catch语句块或者try-catch-finally语句。

    例子:throws

    package lesson_4;
    /**
     * 异常处理机制—2;抛出异常(声明异常)
     * 方法本身有异常,设计师没有处理,在方法的头部声明异常,告诉调用者该方法有异常
     * 调用者在调用方法异常时,要么处理,要么继续抛出异常(throws)
     */
    public class lession_1_1 {
    	/**
    	 * 两整数相除,抛出异常
    	 * @param x  被除数
    	 * @param y  除数
    	 * @return   商
    	 * @throws ArithmeticException  算术异常(除数为0 )  当出现异常的运算条件时,抛出此异常。
    	 */
    	public static int chu(int x,int y) throws ArithmeticException{
    		return x/y;
    	}
    	
    	public static void main(String[] args) {
    		// TODO Auto-generated method stub
    		int x=6;
    		int y=0;
    		int z;
    		 
    		try {
    			z=chu(x, y);
    			System.out.println(x+'/'+y+'='+z);
    		}catch(ArithmeticException e){
    			System.out.println("除数为0");
    		}
    		
    		
    	}
    
    }
    
    

    例子:throw

    package lesson_4;
    /**
     * 学习throw子句(抛出异常)
     * 人工抛出一个异常
     * 即生成一个异常对象
     */
    public class lession_2 {
    
    	public static void main(String[] args) {
    
    		int age;//qq年龄
    		
    		System.out.println("请输入qq年龄:");
    		try {
    			age=Integer.parseInt(args[0]);
    			if(age < 3 || age > 200) {
    				throw new NumberFormatException("qq年龄无效");//人工抛出异常
    				System.out.println("");
    			}
    			System.out.println("请输出年龄:"+age);
    		}catch(NumberFormatException e){
    			System.out.println("输入的不是数字!");
    		}catch(ArrayIndexOutOfBoundsException e) {
    			System.out.println("没有输入!");
    		}catch(Exception e){
    			System.out.println("程序有问题!");
    		}
    			
    		System.out.println("over!");
    	}
    
    }
    

    throw和throws的区别

    ① throw代表动作,表示抛出一个异常的动作;throws代表一种状态,代表方法可能有异常抛出

    ② throw用在方法实现中,而throws用在方法声明中 ,表示此方法在调用时必须处理异常

    ③ throw只能用于抛出一种异常,而throws可以抛出多个异常

    自定义异常

    在 Java 中你可以自定义异常。如果要自定义异常类,则扩展Exception类即可,因此这样的自定义异常都属于检查异常(checked exception)。如果要自定义非检查异常,则扩展自RuntimeException。

    按照国际惯例,自定义的异常应该总是包含如下的构造函数:

    • 一个无参构造函数
    • 一个带有String参数的构造函数,并传递给父类的构造函数。
    • 一个带有String参数和Throwable参数,并都传递给父类构造函数
    • 一个带有Throwable 参数的构造函数,并传递给父类的构造函数。

    例子:

    package lesson_4;
    /**
     * 学习throw子句(抛出异常)
     * 人工抛出一个异常
     * 即生成一个异常对象
     * @author 婷
     *
     */
    public class lession_2 {
    
    	public static void main(String[] args) {
    		// TODO Auto-generated method stub
    		int age;//qq年龄
    		
    		System.out.println("请输入qq年龄:");
    		try {
    			age=Integer.parseInt(args[0]);
    			if(age < 3 || age > 200) {
    				throw new IllegalQQAgeException("qq年龄无效");
    				System.out.println("");
    			}
    			System.out.println("请输出年龄:"+age);
    		}catch(NumberFormatException e){
    			System.out.println("输入的不是数字!");
    		}catch(IllegalQQAgeException e) {
    			e.printStackTrace();
    		}catch(ArrayIndexOutOfBoundsException e) {
    			System.out.println("没有输入!");
    		}catch(Exception e){
    			System.out.println("程序有问题!");
    		}
    			
    		System.out.println("over!");
    	}
    
    }
    package lesson_4;
    /**
     * 自定义异常
     * qq年龄无效异常(年龄大于200或者小于3的时候产生的异常)
     */
    public class IllegalQQAgeException extends Exception{
    
    	public IllegalQQAgeException() {
    		super();
    		
    	}
    	public IllegalQQAgeException(String message) {
    		super(message);
    		
    	}
    	
    }
    
    展开全文
  • Java中异常处理机制

    千次阅读 2018-05-26 11:44:03
    异常处理机制可以在程序发生异常时,对其执行预先设定的异常处理逻辑。Java标准库内建了一些通用的异常。Throwable派生Error、Exception。Error类及其子类代表的是JVM本身的错误,并非程序的问题,不能由程序员通过...
  • Java的异常处理机制

    万次阅读 多人点赞 2018-09-22 18:58:55
    一、什么是java异常? java异常指在程序运行时可能出现的一些错误,如:文件找不到、网络连接失败、非法参数等。异常是一个事件,它发生在程序运行期间,中断了正在执行的程序的正常指令流。Java通过API中Throwable...
  • java(3)-深入理解java异常处理机制

    万次阅读 多人点赞 2011-01-20 18:44:00
    1. 引子 try…catch…finally恐怕是大家再熟悉不过的语句了,而且感觉用起来也是很简单,逻辑上似乎也是很容易理解。不过,我亲自体验的“教训”告诉我,这个东西可不是想象中的那么简单、听话。...
  • 深入理解java异常处理机制-exception

    千次阅读 2017-12-05 14:08:12
    1. 引子  try…catch…finally恐怕是大家再熟悉不过的语句了,而且感觉用起来也是很简单,逻辑上似乎也是很容易理解。不过,我亲自体验的“教训”告诉我,这个东西可不是想象中的那么简单、听话。...
  • java的异常处理机制详解

    千次阅读 2016-08-24 14:35:19
    Java异常处理主要依赖于try,catch,finally,throws,throw这五个关键字。下面分别介绍它们:
  • 一、前言 异常是程序在运行时出现的不正常情况。这个问题按照面向对象思想进行描述,并封装成了对象。因为问题的产生有产生的原因,有问题的名称,有问题的描述等多个属性信息...这样就方便于操作问题以及处理问题。
  • Spring MVC异常处理机制

    2018-07-25 19:55:27
    Java作为一门优秀的开发语言,灵活方便的异常处理机制是它的一大特色。以Java语言为基础的SpringMVC框架也集成封装了异常处理机制,提高了软件的可控性和稳定性,可以处理很多软件运行时发生未知的错误,提高用户...
  • JAVA中的异常处理机制及异常分类

    万次阅读 多人点赞 2017-04-01 16:18:27
    JAVA的异常处理机制:如果某个方法不能按照正常的途径完成任务,就可以通过另一种路径退出方法。在这种情况下会抛出一个封装了错误信息的对象。此时,这个方法会立刻退出同时不返回任何值。另外,调用这个方法的其他...
  • C++异常处理机制

    千次阅读 2018-04-05 17:38:49
    前言 1.异常是一种程序控制机制...2.异常设计目的:  栈机制是一种高度节律性控制机制,面向对象编程却要求对象之间有方向、有目的的控制传动,从一开始,异常就是冲着改变程序控制结构,以适应面向对象程序更有效...
  • Javascript异常处理机制详解

    万次阅读 2017-02-26 13:19:49
    ​ 在Java或C#等一些高级语言中,都提供了异常处理机制,可以处理出现的异常,而不会停止整个应用程序。 ​ 从ES3开始,js也提供了类似的异常处理机制,从而让js代码变的更健壮,及时执行的过程中出现了异常,也...
  • spring异常处理机制

    千次阅读 2017-10-09 20:10:22
    点击阅读原文Spring提供了一系列健全的异常处理框架。我们可以采用@ResponseStatus,@ExceptionHandler,HandlerExceptionResolver以及 @ControllerAdvice处理异常。@ResponseStatus可以为异常指定状态码,可以应用...
  • C语言中的异常处理机制

    万次阅读 多人点赞 2011-05-03 11:09:00
    UNIX 使用信号给出异常,并当发生异常时转跳到信号处理过程进行异常处理。DOS下的信号对比UNIX系统而言相对较少。  我们知道,不管是在c++还是在java中,异常都被认为是一种很优雅的处理错误的机制。而如果想在...
  • SpringMVC异常处理机制详解

    千次阅读 2017-04-30 16:07:04
    目录 前言重要接口和类介绍 HandlerExceptionResolver接口AbstractHandlerExceptionResolver抽象类AbstractHandlerMethodExceptionResolver抽象类ExceptionHandlerExceptionResolver类...
  • 深入理解C++中的异常处理机制

    千次阅读 2015-12-26 21:29:57
    深入理解C++中的异常处理机制异常处理增强错误恢复能力是提高代码健壮性的最有力的途径之一,C语言中采用的错误处理方法被认为是紧耦合的,函数的使用者必须在非常靠近函数调用的地方编写错误处理代码,这样会使得其...
  • 与现实生活中的事件很相似,现实生活中的事件可以包含事件发生的时间、地点、人物、情节等信息,可以用一个对象来表示,Java使用面向对象的方式来处理异常,它把程序中发生的每个异常也都分别封装到一个对象来表示的...
  • C++异常处理机制详解

    千次阅读 2011-11-25 16:06:33
    C++异常处理机制详解 C++自身有着非常强的纠错能力,发展到如今,已经建立了比较完善的异常处理机制. C++的异常情况无非两种,一种是语法错误,即程序中出现了错误的语句、函数结构和类,致使编译程序无法进行。另...
  • Java线程池异常处理机制

    千次阅读 2018-05-15 20:32:42
    不论是直接还是间接,各种服务器...关于线程池的各种文章,多数是关注任务的创建和执行方面,对于异常处理和任务取消(包括线程池关闭)关注的偏少。接下来,本文将从 Java 原生线程、两种主要线程池 ThreadPoolEx...
  • java为什么引入异常处理机制

    千次阅读 2012-11-01 22:29:27
    0. 为什么要引入异常处理机制?  在异常机制引入之前,利用if…else,sysout和syserror的方式处理异常。异常处理是程序设计中一个非常重要的方面,也是程序设计的一大难点,从C开始,你也许已经知道如何用if......
  • SpringBoot之异常处理机制

    千次阅读 2018-07-27 20:32:20
    自定义异常类:UserNotExistException //自定义异常 public class UserNotExistException extends RuntimeException { public UserNotExistException() { super("用户不存在"); } } 2.异常处理器...
  • Java 线程池的异常处理机制

    万次阅读 2017-09-06 01:16:49
    一、前言 线程池技术是服务器端...关于线程池的各种文章,多数是关注任务的创建和执行方面,对于异常处理和任务取消(包括线程池关闭)关注的偏少。 接下来,本文将从 Java 原生线程、两种主要线程池 ThreadPoolEx
  • Java异常处理机制(经典)

    千次阅读 2016-03-21 00:07:38
    目前主流的编程语言如,C++、C#、Java都提供了异常处理机制。增加异常处理机制使程序有更好的兼容性、健壮性。  异常处理是程序设计中一个非常重要的方面,也是程序设计的一大难点,从C开始,也许已用if...else......
  • 深入理解java异常处理机制

    千次阅读 2016-07-12 09:12:29
    try…catch…finally恐怕是大家再熟悉不过的语句了,而且感觉用起来也是很简单,逻辑上似乎也是很容易理解。不过,我亲自体验的“教训” 告诉我,这个东西可不是想象中的那么简单、听话。不信?...
  • java异常处理机制简述

    千次阅读 2014-08-12 10:31:04
    Java的异常处理机制是这样的 try{}是监控的代码,catch{}是处理异常,finally{}是无论是否发生异常,无论异常是否处理都会执行的代码。而finally后面的代码是否执行的关键就是是否有catch语句。catch就是处理异常,...
  • Python异常处理机制

    千次阅读 2017-02-28 21:43:21
    Python 异常处理 python提供了两个非常重要的功能来处理python程序在运行中出现的异常和错误。你可以使用该功能来调试python程序。 异常处理 断言(Assertions) python标准异常 异常名称 描述 ...
  • C++之异常处理机制

    千次阅读 2017-03-07 16:50:19
    一、C++异常处理机制是由3个部分组成:检查(try)、抛出(throw)和捕捉(catch) 把需要检查的语句放在try中,throw用来当出现异常时发生一个异常信息,而catch则用来捕捉异常信息,如果捕捉到了异常信息就处理它...
  • python中的五种异常处理机制

    千次阅读 2018-07-11 13:41:14
    这篇文章主要介绍了python中的五种异常处理机制介绍,本文是Learn Python一书的读书笔记,需要的朋友可以参考下从几年前开始学习编程直到现在,一直对程序中的异常处理怀有恐惧和排斥心理。之所以这样,是因为不了解。...

空空如也

1 2 3 4 5 ... 20
收藏数 1,385,456
精华内容 554,182
关键字:

异常处理机制