异常处理从无知到无畏

为什么要有异常

一个优秀的程序应该有一个标志性的特点,就是他的异常处理相关代码应该要多余实际的业务代码,那这是为什么呢,这个问题有个比较笼统的回答,为了提升程序的健壮性。说白了,我要尽量去掌控自己程序中的异常情况,并且当异常发生时要准确的知道是哪里产生的问题。

java的异常机制是如何做到的呢

我们在程序出现异常的时候都可以看到哪些信息呢,首先调用栈信息,可以看到抛出异常的方法行数,同时可以打印caused by信息,找到异常发生的原因,这些信息是如何打印的呢,计算机没有无缘无故的爱,一定有地方提供了栈信息,并且提供了打印的方法。这里就要说一下java异常处理的祖宗类Throwable,上面的所有功能都是这个类提供的,要想了解java的异常机制,那么这个类是需要弄清楚的。这里先带着大家一起入个门。一言不合先上样例吧,这样看着能更明白点。

	import myexception.MyExcepition;

	public class CatchMain {

    public static int b(){
            c();
            return 1;
    }
    public static int c(){
        try{
            d();
            return 1;
        }catch (MyExcepition ex){
            throw new MyExcepition("这是c打印的错误信息!",ex);
        }
    }

    public static int d(){
        throw new MyExcepition("这是d打印的错误信息!");
    }
    
    public static void main(String[] args) {
        try{
            b();
        }catch (MyExcepition ex){
           ex.printStackTrace();
        }
    }
}


	D:\workspace\study\DesignPattern\out\production\DesignPattern;D:\tools\lombok.jar;D:\tools\jaxb-api-2.0.jar;D:\.m2\repository\mysql\mysql-connector-java\8.0.11\mysql-connector-java-8.0.11.jar CatchMain
myexception.MyExcepition: 这是c打印的错误信息!
	at CatchMain.c(CatchMain.java:14)
	at CatchMain.b(CatchMain.java:6)
	at CatchMain.main(CatchMain.java:24)
Caused by: myexception.MyExcepition: 这是d打印的错误信息!
	at CatchMain.d(CatchMain.java:19)
	at CatchMain.c(CatchMain.java:11)
	... 2 more

Process finished with exit code 0

	package myexception;
	
	public class MyExcepition extends RuntimeException {
	
	    private String msg;
	
	    public MyExcepition(String msg){
	        super(msg);
	        this.msg = msg;
	    }
	
	    public MyExcepition(String msg,Throwable e){
	        super(msg,e);
	        this.msg = msg;
	    }
	}

通过上面的代码,可以先看下自定义 MyExcepition 的继承关系,MyException -> RuntimeException -> Exception -> Throwable ,所有的自定义异常一定要是Throwable的子类,否则 throw new MyException()是无法编译通过的。另外如果细心的读者可能会发现,Exception和RuntimeException这两个子类没有扩展什么方法,功能跟Throwable提供的功能完全一致,那么为什么要多此一举呢,搞这么多子类干啥,这里留一个悬念,大家也想一下。
还有一个问题,大家看下实际上代码中抛出异常的是方法d(),可以栈信息只到了方法c(),栈的链路不完整,这个是为啥,原因在于我在方法c()中进行了一次catch,同时又抛出了一个新的异常,这个异常是覆盖掉了d()方法的异常,这里有个就近原则,可是在caused by中却把d()中的异常信息打印出来了,勾勒出了c和d的异常信息,这个又是因为什么呢,原因在于throwable的一个构造函数,
public MyExcepition(String msg,Throwable e){
super(msg,e);
this.msg = msg;
}
public Throwable(String message, Throwable cause) {
fillInStackTrace();
detailMessage = message;
this.cause = cause;
}
用代码直接对比,可以看到detailMessage,其实就是“这是c打印的错误信息!”而这个this.cause就是
Caused by: myexception.MyExcepition: 这是d打印的错误信息!
at CatchMain.d(CatchMain.java:19)
at CatchMain.c(CatchMain.java:11)
… 2 more
在构造函数中 super(msg,e); 给this.cause赋值,从而拥有了caused by打印的结果,这里的语义就是告诉jvm,我抛出异常了,但是根源不是我错了,而是e。
写着写着感觉有点不易理解,可以多看两遍,掌握这个原理后就可以随心所欲的定义自定义异常,并且可以控制控制台打印的日志内容。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值