彻底掌握JAVA的异常处理


异常:阻止当前方法或作用域继续执行的问题。特别需要注意的,程序抛出异常,不管这个异常是否严重,都必须进行处理,决不能有运算结果不出错就是正常的想法。

先来看看异常有哪些类:

Throwable类是JAVA中所有父类,其下有两个子类:Exception与Error


Error:是指不应该试图捕获的严重问题,是不可恢复的错误,比如内存溢出或虚拟机崩溃。

 

Exception:合理应用程序需要捕抓的条件,Exception包括了CheckException以及RuntimeException,CheckException是指需要在程序中显性指明需要捕抓的异常,而RuntimeException则是可以在程序中不需要显性声明的异常,当发生错误时,直接抛出就是。

其类图关系如下:


先来看看Throwable类的代码,首先Throwable类继承自Serializable接口,表示可以进行序列化为对象,这有利于在网络上传输。

其中,有一个属性定义为Transient,如下:

    private transient Object backtrace;

表示该属性是透明的,不需要序列化为对象的。


  private StackTraceElement[] stackTrace;//描述异常轨迹的数组


StackTraceElement是一个堆栈描述类,包括了方法名、类名、文件名、行号,用于描述堆栈信息。


fillInStackTrace()是一个声明为native的函数,从调用的位置起记录新堆栈。


public String getMessage() {

        return detailMessage;

    }

    public String getLocalizedMessage() {

        return getMessage();

    }

getMessage与getLocalizedMessage实际上返回的信息是一样的,如果要加入本地化信息,需要自己在子类中重写。

 

getCause():获取异常的起因对象,是异常链的一部分

initCause():初始化异常原因

toString():格式化异常信息

printStackTrace():打印堆栈跟踪

getOurStackTrace()获取当前堆栈信息

private native intgetStackTraceDepth();获取当前堆栈信息的深度,0表示堆栈不可用

private native StackTraceElement getStackTraceElement(int index);根据索引获取某个堆栈对象

再看看Exception类与Error类、RuntimeException:

方法基本都是继承自Throwable的,即使是构造函数也是调用父类的进行初始化

 

 

异常处理需要注意的地方:

(1)      所有的catch都用Exception 或Throwable来捕抓

    try{

           //dothong

       }

       catch(Exception e){

           e.printStackTrace();

       }

这样捕抓异常,虽然程序不会出错,但程序员无法知道异常的类型,并对其作分别处理,所以,异常必须尽可能捕抓且分开处理,这样才能提高程序的健壮性。

 

(2)接口污染

public interface aaa{

    void readData() throws SQLException;

}

public class StudyInfoimplements aaa {

 

    @Override

    public void readData() throws SQLException {

       try{

           //do something

       }

       catch(SQLException e)

       {

           e.printStackTrace();

            throw e;

       }

      

    }

}

可以看出,以上的接口污染,导致了以后所有继承该接口的类都要抛出SQLException异常,即使没有SQLException也要造一个出来。代码完全可以写成抛出RunTimeException,代码如下:

public interface aaa{

    void readData();

}

public class StudyInfoimplements aaa {

 

    @Override

    public void readData(){

       try{

           //do something

       }

       catch(SQLException e)

       {

           throw new RuntimeException(e);

       }

      

    }

}

这样修改后,程序就变得灵活了很多。

(3) 所有的异常都比较消耗性能,捕获异常时,必须进行处理,否则异常会一层一层向外抛,直到Object对象为止。

(4)throw与throws是有区别的,throws 关键字通常被应用于声明方法时,用来指定可能抛出的异常,多个异常可以用逗号隔开。而throw关键字是抛出某个具体的对象

 

再提一个执行顺序的问题来加深对Exception的理解:

 

try{}里有一个return语句,那么紧跟在这个try之后的finally{}里的代码会不会执行,什么时候执行?是在return前还是return后?

 

答案:会执行,而且在return之后执行,即使是被throw出去后也会执行

因此可以看出,程序执行return时,函数并不会真正返回,只是把返回结果放到函数栈中,等finally语句执行后才真正返回。


 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值