未将对象引用到对象的实例
前天改了个bug,是初学者很常见的一个bug,“未将对象引用到对象的实例”。
起初看到这个bug的时候,我不屑一顾,无非就是后端使用某对象的时候,判断下null再使用就行了,因此断点调试我也是这么观测的。随手一改,调试到指定位置看到抛异常的地方,就加上if-else了,甚至懒得再继续调试,问题就在这里。
然鹅,鬼使神差的突然想继续调试下,这一下不得了!断点往下继续走,在其他的地方也抛异常了,依然是对象为null导致的。
什么对象呢?姑且称之为userInfo,后端接口里使用的时候直接userInfo.UserId访问了,如果userInfo = null,就会抛标题中的这个问题。一般的,我们系统是需要登录的,userInfo正常不会为null,但是巧就巧在,当换个身份以及入口进行登录时,这个userInfo就有可能为null,另外一个身份的用户信息并不是记在这个对象里的(并不是什么都往这个对象里存,代码里的变量也不是叫userInfo,也不一定是存用户信息,只是说,有类似这么个东西,这里不过多探讨)。
那么怎么处理呢,最开始想的自然是该接口每个涉及的地方,都判断下再使用,避免报这个“低级”错误。
经过对代码的阅读,发现其实并不好改,并不是每个地方加上if-else就完事的,if里不为空可以走逻辑,但是else没数据,可是不行的。因此在加完第一个地方的判断后,我就发现后续一些用到这个对象的地方,对象本身不能为null,否则逻辑无法走通。即便改了,也并不一定是对的(记住这句话)。
所以进一步思考,为什么这个对象为null?以前怎么没报这个错误?这个方法哪些地方在调用,是否调用的地方不同,导致这里有一些场景没有考虑?或者说,在某些场景里,这个对象是否也应该赋值一下?于是乎,我看了下这个对象的赋值逻辑,果然在场景2中,该对象没有赋值。那么是不是在场景2里对userInfo赋值一下就完事了呢?并不是。
首先我排查了场景1和场景2,最近的改动不涉及对userInfo的赋值,所以很明显并不是针对赋值改出来的bug,场景1赋值,场景2不赋值,以前就是这样,既然以前就是这样,那以前怎么不报错?以前不走这里?嗯?——对,场景2的时候,不走这里!我一下子就转过来了。
请求接口的时候这个对象确实为null,导致报错,那么,为什么场景2的时候,要请求这个接口呢?这,才是关键!
经过对业务的理解和,场景2是无需请求这个接口的,这里请求了,很明显跟最近的改动有关,最后发现是某个公共JS修改导致。解决办法就是在JS里做下兼容,修复该页面的bug,使其和以前保持一致,场景2时不请求接口,这样也就不会有“未将对象引用到对象的实例”这个错误了。
初看这个问题是不是很简单,从编程入门,到多年开发,其实很难绕开这个, 尤其一些项目运作了很久,代码成千上万行,很难保证修改某个地方的时候不会影响其他地方,从而导致一些奇怪的,亦或低级的bug。不过这里要说的并不是这个问题的难易,而是当我们改一个bug的时候,先想想,是什么bug,为什么要改,要怎么改,改哪里,说简单点就是,抛异常的地方并不一定就是要改的地方,很可能要改的地方在这段代码更前面。很多时候,要从源头解决问题。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步