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

2024-02-21 10:59

本文主要是介绍到底怎样写 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 黑话大全,太真实了!

编程·思维·职场
欢迎扫码关注

640?wx_fmt=jpeg

这篇关于到底怎样写 try-catch,才能称之为高手?的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/731548

相关文章

秒变高手:玩转CentOS 7软件更换的方法大全

在 CentOS 7 中更换软件源可以通过以下步骤完成。更换源可以加快软件包的下载速度,特别是当默认源速度较慢时。以下是详细步骤: 前言 为了帮助您解决在使用CentOS 7安装不了软件速度慢的问题,我们推出了这份由浪浪云赞助的教程——“CentOS7如何更换软件源加快下载速度”。 浪浪云,以他们卓越的弹性计算、云存储和网络服务受到广泛好评,他们的支持和帮助使得我们可以将最前沿的技术知识分

C++第四十七弹---深入理解异常机制:try, catch, throw全面解析

✨个人主页: 熬夜学编程的小林 💗系列专栏: 【C语言详解】 【数据结构详解】【C++详解】 目录 1.C语言传统的处理错误的方式 2.C++异常概念 3. 异常的使用 3.1 异常的抛出和捕获 3.2 异常的重新抛出 3.3 异常安全 3.4 异常规范 4.自定义异常体系 5.C++标准库的异常体系 1.C语言传统的处理错误的方式 传统的错误处理机制:

LabVIEW程序员是怎样成长为大佬

成为一名LabVIEW编程领域的“大佬”需要时间、实践、学习和解决复杂问题的经验。尽管LabVIEW作为一种图形化编程语言在初期可能相对容易上手,但要真正成为精通者,需要在多个层面上深入理解。以下是LabVIEW程序员如何逐步成长为“大佬”的路径: 1. 打好基础 LabVIEW的大佬们通常在初期会打下非常坚实的基础,理解LabVIEW编程的核心概念,包括: 数据流编程模型:Lab

【H2O2|全栈】Markdown | Md 笔记到底如何使用?【前端 · HTML前置知识】

Markdown的一些杂谈 目录 Markdown的一些杂谈 前言 准备工作 认识.Md文件 为什么使用Md? 怎么使用Md? ​编辑 怎么看别人给我的Md文件? Md文件命令 切换模式 粗体、倾斜、下划线、删除线和荧光标记 分级标题 水平线 引用 无序和有序列表 ​编辑 任务清单 插入链接和图片 内嵌代码和代码块 表格 公式 其他 源代码 预

十四、我们应当怎样做需求分析:子用例与扩展用例

用例模型作为UML中4+1视图中非常重要的一员,非常集中地体现了面向对象的分析与设计思想。用例模型将现实世界中连续的一个一个业务流程,按照场景划分到了一个一个的用例中。由于场景的出现,使得用例中的业务流程存在着高度的内聚性,从而成为了日后各种对象的雏形。同时,在用例分析中,又将那些存在于各个用例中的,相同或相近的业务操作提取出来,形成一个一个的子用例或扩展用例,又体现了面向对象设计中的复用性。现在

十三、我们应当怎样做需求分析:查询报表分析

在我以往的用例分析中,使用这样格式的用例模式,对于大多数业务操作流程来说是得心应手的,但对于有些功能来说总感觉不对劲。感觉不对劲的,就是那些查询、汇总与报表功能。对于这部分功能,需要我们描述的不是什么操作流程,而更重要的是那些数据项、数据来源、报表格式、数据链接,以及使用者、使用频率的说明。而这些,在以往的用例说明格式中统统都没有,怎么办呢?俗话说“东西是死的人是活的”,把我们的用例格式改改吧。

九、我们应当怎样做需求分析:功能角色分析与用例图

在我们进行一系列需求调研工作的同时,我们的需求分析工作也开始启动了。需求调研与需求分析工作应当是相辅相伴共同进行的。每次参加完需求调研回到公司,我们就应当对需求调研的成果进行一次需求分析。当下一次开始进行需求调研时,我们应当首先将上次需求分析的结果与客户进行确认,同时对需求分析中提出的疑问交给客户予以解答。这就是一个需求捕获->需求整理->需求验证->再需求捕获的过程。  但是,当我们经

八、我们应当怎样做需求调研:需求捕获(下)

前面我们讨论了,需求分析工作是一个迭代的过程:需求捕获->需求整理->需求验证->再需求捕获······需求捕获是这个迭代过程的开始,也是整个需求分析工作中最重要的部分。没有捕获哪来后面的整理与验证工作?但是,非常遗憾,按照我以往的经验,需求捕获是我们最薄弱的环节。前面我提到的许许多多项目开发的问题都可以归结为需求分析的问题,而许许多多需求分析的问题又都可以归结为需求捕获不完整的问题。需求捕获是整

七、我们应当怎样做需求调研:需求捕获(上)

前面我们讨论了,需求分析工作是一个迭代的过程:需求捕获->需求整理->需求验证->再需求捕获······需求捕获是这个迭代过程的开始,也是整个需求分析工作中最重要的部分。没有捕获哪来后面的整理与验证工作?但是,非常遗憾,按照我以往的经验,需求捕获是我们最薄弱的环节。前面我提到的许许多多项目开发的问题都可以归结为需求分析的问题,而许许多多需求分析的问题又都可以归结为需求捕获不完整的问题。需求捕获是整

六、我们应当怎样做需求调研:迭代

前面我一直在反复强调这样一个观点,需求分析不是一蹴而就的,是一个反复迭代的过程。它将从第一次需求分析开始,一直持续到整个项目生命周期。为什么这样说呢?让我们一起来分析分析。  在第一次的需求分析阶段,我们在一段时期内需要与客户进行反复地讨论,这个过程往往是这样一个反复循环的过程:需求捕获->需求整理->需求验证->再需求捕获••••••  需求捕获,就是我们与客户在一起开研讨会