美文网首页Android开发Android开发经验谈Android技术知识
到底怎样写 try-catch,才能称之为高手?

到底怎样写 try-catch,才能称之为高手?

作者: bfc7f634299a | 来源:发表于2019-08-23 10:50 被阅读7次

    try-catch,一个大家最常见不过的语法,但是有些人却用不好。当面对一个崩溃的时候,不管三七二十一先catch住再说,没错,老崩溃是被catch住了,但是新崩溃又出现了,想想都是坑啊,本文就和大家探讨下这个话题,此外买一送一,再和大家探讨下空指针异常。

    乱用try-catch

    写过C++的人都知道,那异常捕获特别不好用,甚至有些异常还捕获不了,在Java中,try-catch特别好使,如果一个人的代码没有try-catch,有时候会被大家质疑代码写的不健壮。

    try-catch虽好,但不可乱用,原因在于try-catch可以隐藏代码缺陷,不利于bug排查。如果没有try-catch,那程序会崩溃,崩溃后从日志中可以一眼看出问题的原因。而如果用了try-catch以后,崩溃被catch住了,这个时候程序没有崩溃,但是程序运行会不正常。

    我相信大家都明白:crash并不可怕,可怕的是crash后却没有找到日志,你就慢慢去查吧,这感觉谁查谁知道。

    举个例子来说明下:

    public class Example {
        public static void main(String[] args) {
    
            BusinessLogic bl = new BusinessLogic();
            bl.doA();
            bl.doB();
            bl.doC();
            bl.doD();
            bl.doE();
    
        }
    
    }
    
    
    class BusinessLogic {
    
        public void doA(){
            System.out.println("I am doing A");
        }
    
        public void doB(){
            System.out.println("I am doing B");
        }
    
        public void doC(){
            int i = 1/0;
            System.out.println("I am doing C");
        }
    
        public void doD(){
            System.out.println("I am doing D");
        }
    
        public void doE(){
            System.out.println("I am doing E");
        }
    }
    
    

    上面的程序有个问题,在doC函数中存在除0异常,程序运行后会崩溃,我们可以得到如下日志反馈:

    I am doing A
    I am doing B
    Exception in thread "main" java.lang.ArithmeticException: / by zero
        at BusinessLogic.doC(Example.java:27)
        at Example.main(Example.java:7)
    sandbox> exited with status 0
    
    

    但是有的程序员,特别害怕崩溃,为了让自己的程序不会崩溃,直接在最外层进行try-catch:

    public class Example {
        public static void main(String[] args) {
            try {
                BusinessLogic bl = new BusinessLogic();
                bl.doA();
                bl.doB();
                bl.doC();
                bl.doD();
                bl.doE();
            } catch(Exception e) {
                e.printStackTrace();
            }
        }
    
    }
    
    

    结果,程序是不会崩溃了,但是逻辑并没有正确地执行,这个时候如果让你去排查这个问题,你能第一时间定位到doC函数有问题吗?我觉得大部分人都不能。

    虽然这个例子看起来有点可笑,但是在实际开发中确实看到过不少这种现象,更有甚者,连e.printStackTrace()这句话都懒得加,程序没有任何异常日志,想排查这种错误简直痛不欲生。

    空指针强迫症

    前面说到崩溃,大家知道排名前2的崩溃是什么吗?没错,那就是:
    NullPointerException
    IndexOutOfBoundsException

    大家可以检查下自己的项目,看看这两个异常是不是占大头。所以,为了防止空指针异常,很多程序员会这样写代码:

    public class Example {
        public static void main(String[] args) {
            BusinessLogic bl = new BusinessLogic();
            Object param = new Object();
            bl.doA(param);
        }
    
    }
    
    
    class BusinessLogic {
    
        public void doA(Object o){
            if (o != null) {
                System.out.println("I am doing A with param : " + o);
                doB(o);
            }
        }
    
        public void doB(Object o){
            if (o != null) {
                System.out.println("I am doing B with param : " + o);
                doC(o);
            }
        }
    
        public void doC(Object o){
            System.out.println("I am doing C with param : " + o);
        }
    
    }
    
    

    上面程序犯了一个错误,那就是重复判空,大量的冗余判断会影响程序的性能,上面的例子很简单,我相信大家都不会犯这个错误,但是当项目大了以后,当函数调用错综复杂的时候,你还能保证自己不犯错吗?很难!

    大家还记得C语言的strcpy函数吗?

    strcpy(char * __restrict to, const char * __restrict from)
    {
        char *save = to;
    
        for (; (*to = *from); ++from, ++to);
        return(save);
    
    

    可以看到,C语言的strcpy函数,没有进行任何判断,比如你传递个空,或者说to的长度比from小,这些都会导致程序异常,但strcpy依然是不做任何判断,为的就是追求高性能。

    对于strcpy来说,异常判断是上层调用方该考虑的事情,它作为底层API并不需要关注那么多,如果上层调用不合法,那就让程序挂掉就行了,谁叫你不按我的要求来呢!

    这个涉及到架构设计的理念,我们在开发一个sdk的时候,其实是不需要每次都校验参数合法性的,明确对外暴露的API,如果说外部调用不合法,一定要让程序挂掉,而不是不回应,这样上层也更好排查问题,尤其是一些调用频次较高的底层sdk,更要注重这一点,性能和调用反馈是我们需要注意的。

    这就好比搭积木,我们无需保证每块积木都是完全可靠的,但是每个积木之间无缝衔接,没有多一点,也没有少一点,而是刚刚好,它们共同构成了一个完整健壮的个体。写程序也是如此:

    无需做诸多冗余的保证,只要各层级的代码能够无缝衔接就好

    这就是我心中的代码设计理念,大道至简,简单到每个人都能理解。

    相关文章

      网友评论

        本文标题:到底怎样写 try-catch,才能称之为高手?

        本文链接:https://www.haomeiwen.com/subject/eljzsctx.html