Java异常

异常概述java

异常也称为例外,是在程序运行过程当中发生的而且会打断程序正常执行的事件,好比算术异常、空指针异常、文件找不到异常。因此在程序设计时,必须考虑到可能发生的异常事件,并作出相应的处理。这样才能保证程序能够正常运行。数组

Java的异常处理机制也秉承着面向对象的基本思想,在Java中,全部的异常都是以类的形式存在,除了内置的异常类以外,Java也能够自定义异常类。此外,Java的异常处理机制也容许自定义抛出异常。网络

 

为何要使用异常架构

在没有异常处理的语言中,就必须使用if或switch等语句,配合所想获得的错误情况来捕捉程序里全部可能发生的错误。但为了捕捉这些错误,编写出来的代码常常有不少的if语句,有时候这样也未必能捕捉到全部的错误,并且这样作势必致使程序运行效率的下降。Java的异常处理机制刚好改进了这一点,它易于使用而且可自行定义异常类,可是不得不说,异常也是一个较为耗费性能的操做,所以咱们须要合理地利用Java的异常处理机制,以增进程序的稳定性和效率。性能

 

异常的继承架构spa

异常可分为两大类:java.lang.Exception与java.lang.Error,这两个类均继承自java.lang.Throwable,上图为Throwable类的继承关系图。设计

习惯上将Error与Exception统称为异常类,但这二者本质上仍是有不一样的:指针

一、Error专门用来处理严重影响程序运行的错误,但是一般程序设计者不会涉及程序代码去捕捉这种错误,其缘由在于即便捕捉到它,也没法给予适当的处理,好比Java虚拟机出错就属于一种Errorcode

二、Exception包含了通常性的异常,这些异常一般在捕捉到以后即可以作妥善的处理,以确保程序继续运行对象

从继承架构图中能够看出,Exception扩展出数个子类,其中IOException、RuntimeException是较经常使用的两种。RuntimeException即便不编写异常处理的程序代码,依然能够编译成功,而这种异常必须是在程序运行时才有可能发生,好比数组索引值超出了范围。与RuntimeException不一样的是,IOException必定要编写异常处理的程序代码才行,它一般用来处理输入/输出相关的操做,如对文件的访问、网络的链接等。

当异常发生时,发生异常的语句代码会抛出一个异常类的实例化对象,以后此对象与catch语句中的类的类型进行匹配,而后在相应的catch中进行处理。

 

try、catch、finally、throw、throws

当异常发生时,一般能够用两种方法来处理:

一、交由Java默认的异常处理机制作处理,但这种处理方式,Java一般只能输出异常信息,接着便终止程序的运行,好比:

 1 public static void main(String[] args) throws InterruptedException
 2 {
 3     operateNull(null);
 4     System.out.println("After operateNull");
 5 }
 6 
 7 public static char operateNull(String str)
 8 {
 9     return str.charAt(0);
10 }

返回结果为:

Exception in thread "main" java.lang.NullPointerException
    at com.xrq.test33.TestMain.operateNull(TestMain.java:13)
    at com.xrq.test33.TestMain.main(TestMain.java:7)

和"接着便终止程序的运行"一致,由于第4行的语句并无打印。

二、自行编写try-catch-finally块来捕捉异常,这种写法的最大好处是,能够灵活操控程序的流程且可作出最适当的处理,好比:

 1 public static void main(String[] args) throws InterruptedException
 2 {
 3     try
 4     {
 5         Thread.sleep(1000);
 6         operateNull(null);
 7     } 
 8     catch (NullPointerException e)
 9     {
10         System.out.println("NullPointerException's catch block!");
11         throw e;
12     }
13     finally
14     {
15         System.out.println("NullPointerException's finally block!");
16     }
17 }
18 
19 public static char operateNull(String str)
20 {
21     return str.charAt(0);
22 }

返回结果为:

1 NullPointerException's catch block!
2 NullPointerException's finally block!
3 Exception in thread "main" java.lang.NullPointerException
4     at com.xrq.test33.TestMain.operateNull(TestMain.java:25)
5     at com.xrq.test33.TestMain.main(TestMain.java:10)

关于这段代码解释每一个关键字:

(1)try表示要检查的程序语句

(2)catch表示异常发生时的处理语句,可省略

(3)finally表示不管catch内部写了什么,即便是return,也都会运行到的语句,可省略。finally经常使用于对某段待检查的代码作扫尾工做,好比ReentrantLock的unlock()、IO的close()

(4)throw表示抛出一个类的实例,注意实例二字,实例意味着throw出去的是一个实例化的异常对象。因此代码的11行也能够写为"throw new NullPointerException()",至于为何不这么写,由于写"throw new NullPointerException()"并无返回结果中第4行、第5行中的异常堆栈。注意,throw关键字能够写在任何地方,并不强制必须写在catch块中,运行到throw所在的行,打印异常并当即退出当前方法

(5)throws用于方法声明,表示若是方法内的程序代码可能会发生异常,且方法内又没有使用代码的代码块来捕捉这些异常时,则必须在声明方法时一并指明全部可能发生的异常,以便让调用此方法的程序得以作好准备来捕捉异常。好比"方法名称(参数...) throws 异常类1, 异常类2, 异常类3...",也能够不这么麻烦,Exception是全部异常的父类,所以也能够直接"方法名称(参数...) throws Exception"

 

异常场景汇总

异常细节诸多,以前我也一直有搞不清楚的地方,所以这里对多种场景作一个总结、汇总:

一、接口方法能够throws异常,但必须throws一个具体的异常,不能直接throws出去Exception

public interface InterfaceException
{
    void ExceptionMethod() throws NullPointerException;
}

二、接口方法throws异常,其实现类实现该方法的时候不强制必须抛出该异常,也能够任意抛出异常

public class InterfaceExceptionImpl implements InterfaceException
{
    public void ExceptionMethod()
    {
        
    }
}
public class InterfaceExceptionImpl implements InterfaceException
{
    public void ExceptionMethod() throws ArrayIndexOutOfBoundsException
    {
        
    }
}

三、catch块内若是捕获到了异常而且throw出去了e,那么方法以后的代码都不会再运行了;catch块内若是捕获到了异常,可是没有throw出去e,也没有任何致使程序终止的语句,那么try...catch...finally以后的语句仍然能够继续运行

四、捕获异常不能够先catch (Exception e){...}再catch (NullPointerException e)

缘由是"Unreachable catch block for NullPointerException. It is already handled by the catch block for Exception",即Java检测到NullPointer这个异常是不可达的

五、方法A声明throws异常,则调用方法A的代码必须try...catch...该异常

六、方法A声明throws出Exception,调用方法A的代码必须try...catch...该异常,若是:

(1)有匹配异常的catch块,则优先走匹配异常的catch块

(2)若是没有匹配异常的catch块,可是有catch (Exception e){...},则走catch (Exception e){...}

(3)若是没有没有匹配的catch块,则调用方法A的地方throw异常,方法终止

七、若是方法中没有try...catch异常而该方法发生了异常,且方法声明中有throws,那么发生的该异常能够被抛到调用方法的代码中

八、若是方法中对某个代码块作了try...catch而且想把catch到的异常抛给调用方法的地方,那么:

(1)不能够只有throw没有throws,这将会致使捕获到的异常没法被抛给调用方法的地方

(2)不能够只有throws没有throw,这将会致使编译出错

只有在catch块中throw捕获到的异常而且在方法声明的地方throws异常,才能够将一个异常正确地抛给调用方法的地方

相关文章
相关标签/搜索