详解Java异常

详解Java异常

异常的定义:

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

看一段简单的代码:

public static void main(String[] args) {

        // TODO Auto-generated method stub

        System.out.println("异常测试开始");

        System.out.println(1/0);

        System.out.println("异常测试结束");

    }

运行后,输出如下所示:

Exception in thread "main" 异常测试开始

java.lang.ArithmeticException: / by zero

    at Demo.main(Demo.java:12)

显然这段代码出现了:除数为0的异常。出现异常后,它后面的语句 System.out.println("异常测试结束");没有被执行,可见异常的出现干扰了正常的指令流程。

除数为0这种异常属于java中的ArithmeticException,Java异常类层次结构图如下所示:

Java异常类层次结构图

如上图所示,Throwable: 有两个重要的子类:Exception(异常)和 Error(错误),二者都是 Java 异常处理的重要子类,各自都包含大量子类。

Error(错误):

是程序无法处理的错误,表示运行应用程序中较严重问题。大多数错误与代码编写者执行的操作无关,而表示代码运行时JVM(Java 虚拟机)出现的问题。例如,Java虚拟机运行错误(Virtual MachineError),当 JVM不再有继续执行操作所需的内存资源时,将出现OutOfMemoryError。这些异常发生时,Java虚拟机(JVM)一般会选择线程终止。这些错误表示故障发生于虚拟机自身、或者发生在虚拟机试图执行应用时,如Java虚拟机运行错误(VirtualMachineError)、类定义错误(NoClassDefFoundError)等。这些错误是不可查的,因为它们在应用程序的控制和处理能力之外,而且绝大多数是程序运行时不允许出现的状况。对于设计合理的应用程序来说,即使确实发生了错误,本质上也不应该试图去处理它所引起的异常状况。在Java中,错误通过Error的子类描述。

Exception(异常):

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

异常的对象来源:

有两个来源,一是Java运行时环境自动抛出系统生成的异常,而不管你是否愿意捕获和处理,它总要被抛出!比如除数为0的异常。二是程序员自己抛出的异常,这个异常可以是程序员自己定义的,也可以是Java语言中定义的,用throw关键字抛出异常,这种异常常用来向调用者汇报异常的一些信息。

异常的分类:

通常,Java的异常(包括Exception和Error)分为可查的异常(checked exceptions)和不可查的异常(unchecked exceptions)。

可查异常(编译器要求必须处置的异常):

正确的程序在运行中,很容易出现的、情理可容的异常状况。可查异常虽然是异常状况,但在一定程度上它的发生是可以预计的,而且一旦发生这种异常状况,就必须采取某种方式进行处理。除了RuntimeException及其子类以外,其他的Exception类及其子类都属于可查异常。这种异常的特点是Java编译器会检查它,也就是说,当程序中可能出现这类异常,要么用try-catch语句捕获它,要么用throws子句声明抛出它,否则编译不会通过。

不可查异常(编译器不要求强制处置的异常):

包括运行时异常(RuntimeException与其子类)和错误(Error)。

运行时异常:都是RuntimeException类及其子类异常,如NullPointerException(空指针异常)、IndexOutOfBoundsException(下标越界异常)等,这些异常是不检查异常,程序中可以选择捕获处理,也可以不处理。这些异常一般是由程序逻辑错误引起的,程序应该从逻辑角度尽可能避免这类异常的发生。运行时异常的特点是Java编译器不会检查它,也就是说,当程序中可能出现这类异常,即使没有用try-catch语句捕获它,也没有用throws子句声明抛出它,也会编译通过。

错误(Error)描述了Java运行时系统的内部错误和资源耗尽错误。应用程序不应该抛出这种异常错误!

异常关键字:

Java异常处理通过5个关键字try、catch、throw、throws、finally进行管理。基本过程是用try语句块包住要监视的语句,如果在try语句块内出现异常,则异常会被抛出,你的代码在catch语句块中可以捕获到这个异常并做处理;还有以部分系统生成的异常在Java运行时自动抛出。你也可以通过throws关键字在方法上声明该方法要抛出异常,然后在方法内部通过throw抛出异常对象。finally语句块会在方法执行return之前执行,一般结构如下:

try{

程序代码

 }catch(异常类型1 异常的变量名1){

程序代码

 }catch(异常类型2 异常的变量名2){

程序代码

}finally{

程序代码

 }

try...catch

典型的异常代码示例如下所示:

public static void main(String[] args) {

        // TODO Auto-generated method stub

        System.out.println("异常测试开始");

        try{

            System.out.println(1/0);

        }catch(ArithmeticException e){

            System.out.println("捕获算数异常");

            e.printStackTrace();

        }

        System.out.println("异常测试结束");

    }

运行结果如下:

异常测试开始

捕获算数异常

异常测试结束

java.lang.ArithmeticException: / by zero

    at Demo.main(Demo.java:10)

由此可见,当异常发生时,异常处理机制成功捕获到了异常(执行catch中的代码),保障了程序的继续运行(代码System.out.println("异常测试结束");成功执行。)

更改上面的代码中的异常类型为NullPointerException,代码如下所示:

    System.out.println("异常测试开始");

        try{

            System.out.println(1/0);

        }catch(NullPointerException e){

            System.out.println("捕获算数异常");

            e.printStackTrace();

        }

        System.out.println("异常测试结束");

运行结果如下:

异常测试开始

Exception in thread "main" java.lang.ArithmeticException: / by zero

    at Demo.main(Demo.java:11)

由此可见,当使用错误的异常类型进行异常处理时,是无法捕获异常的!所以当你不知道具体的异常类型时可以使用类Exception,它是各种异常的父类,更改上面的代码中异常类型为Exception,代码如下所示:

      System.out.println("异常测试开始");

        try{

            System.out.println(1/0);

        }catch(Exception e){

            System.out.println("捕获算数异常");

            e.printStackTrace();

        }

        System.out.println("异常测试结束");

运行结果如下:

异常测试开始

捕获算数异常

异常测试结束

java.lang.ArithmeticException: / by zero

    at Demo.main(Demo.java:11)

由此可见,使用Exception可以成功处理该异常。这种方式的优点是可以轻松的处理各种异常,但缺点是不能针对不同种类的异常进行不同的编码处理。

finally

关于finally{}的含义就是:无论代码有无异常发生,都会执行finally中的代码,这里就不多做解释了。

关于throw和throws 的解释如下:

throws

throws语句用在方法声明后面, 表示方法中可能存在的Exception 将抛出异常给调用此方法的方法,当前方法不做异常的处理,但是调用该方法时必须进行异常处理,否则ide会提示错误,如下图所示:

throw

throw语句用在方法体内,表示抛出异常程序在执行到throw语句时立即停止,它后面的语句都不被执行。

代码如下所示:

public static void expfun2(int a,int b) {  

        System.out.println("异常测试开始");

        if (b==0)

{

     throw new ArithmeticException();   

}

        System.out.println(a/b);   

        System.out.println("异常测试结束");

    }

调用方法expfun2(8,0);运行结果如下:

异常测试开始

Exception in thread "main" java.lang.ArithmeticException

    at Demo.expfun2(Demo.java:28)

    at Demo.main(Demo.java:10)

throw和throws区别如下:

1. throw是抛出了异常,执行throw则一定抛出了某种异常;throws表示出现异常的一种可能性,并不一定会发生这些异常。

2、throw用在方法实现中;而throws用在方法声明中。

3、throw只能用于抛出一种异常;而throws可以抛出多个异常

自定义异常

如果Java自带的异常不能满足我们业务的需求, 这个时候我们可以自定义异常来进行对业务异常的处理。最简单的实现自定义异常的方法就是创建一个类,继承其中想要自定义的异常类,重写他的构造方法。

自定义异常代码实现如下:

public classMyExceptionextends Exception {

    public MyException()

   {

    }

    publicMyException(String str) {

        super(str);

    }

}

使用自定义异常代码如下:

public static void expfun8(int a, int b) throws MyException{

        System.out.println("异常测试开始");

        if (b== 0) {

            throw new MyException("自定义异常!");

        }

        System.out.println(a/ b);

        System.out.println("异常测试结束");

    }

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,907评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,987评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,298评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,586评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,633评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,488评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,275评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,176评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,619评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,819评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,932评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,655评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,265评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,871评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,994评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,095评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,884评论 2 354