本文主要是介绍到底怎样写 try-catch,才能称之为高手?,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
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 zeroat 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的崩溃是什么吗?没错,那就是:
大家可以检查下自己的项目,看看这两个异常是不是占大头。所以,为了防止空指针异常,很多程序员会这样写代码:
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,更要注重这一点,性能和调用反馈是我们需要注意的。
这就好比搭积木,我们无需保证每块积木都是完全可靠的,但是每个积木之间无缝衔接,没有多一点,也没有少一点,而是刚刚好,它们共同构成了一个完整健壮的个体。写程序也是如此:
无需做诸多冗余的保证,只要各层级的代码能够无缝衔接就好
这就是我心中的代码设计理念,大道至简,简单到每个人都能理解。
以上就是我要分享的,原创不易,给点个在看呗,大家周四快乐!
推荐阅读你们吹捧的鸿蒙,只是另一个Fuchsia探索Flutter异步消息的实现互联网 HR 黑话大全,太真实了!
编程·思维·职场
欢迎扫码关注
这篇关于到底怎样写 try-catch,才能称之为高手?的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!