大家用IDEA写Java是不是也会经常遇到我遇到的这种情况
昨天我在写一段 Java 代码,大概是这样的:
X.getBar().hashCode();getBar()是可能返回null的。IDEA 很贴心地飘了个黄,提示我“这玩意儿可能为空”。
我心想,行吧,那就加个检查。于是我把光标挪上去,等那个熟悉的灯泡弹出来。
没有灯泡。
我盯着屏幕看了三秒,又点了一下Alt+Enter,看看有没有什么隐藏选项。结果弹出的是那种“你确定要这么写吗”的通用提示,没有“加断言”,没有“包 if 检查”。
我叹了口气,手动改成了:
Objectbar=X.getBar();if(bar!=null){bar.hashCode();}改完之后,IDEA 满意了,黄线消失了。但我心里不太满意——这三行字,明明应该是它帮我写的。
这也让我再一定程度上养成了防御性编码,很多时候也不会采用链式调用的方式
后来我才知道,我不是唯一一个被这件事烦到的人。
这个 问题是 11年前就被网友提了。 他在里面写得清清楚楚:
用户可以通过“引入变量”再加意图操作来实现,但这本可以自动化。
为什么会等这么久呢?
IDEA 的might be null检查,本质上是在分析表达式的结果。
如果表达式是个简单的变量引用,比如bar,它能轻松追踪这个变量的来源,于是就能给出“加断言”或者“包 if”的修复建议。
但当表达式是X.getBar().hashCode()这种链式调用时,情况就复杂了。IDEA 要判断getBar()的返回值是否可能为空,还要处理这个返回值在整条链里的位置。在 11 年前的实现里,它选择了一个偷懒的策略:
复杂表达式,我只警告,不帮你修。
于是你就得到了一个很尴尬的体验:IDEA 知道这里有风险,但它不伸手。
现在,它终于伸手了
这个新特性要干的事,就是把那根断了 11 年的线接上。
当你在一个链式调用里遇到“可能为空”的警告时,IDEA 现在能自动帮你把复杂表达式抽成一个局部变量,然后在这个变量上做 null 检查。它提供两个选项:
选项一:加断言
Objectbar=X.getBar();assertbar!=null;bar.hashCode();选项二:包一层 if
Objectbar=X.getBar();if(bar!=null){bar.hashCode();}两个选项的本质是一样的:先把X.getBar()的结果存下来,再检查它是不是 null,最后再调用方法。
你只需要按一下Alt+Enter,选一个,代码就改好了。
IDEA 的 null 检查已经做得非常强了,但它在一个很小的分支上(复杂表达式)选择了“不做”。这个选择在当年可能是合理的,11 年后就成了一个谁都想修、但谁都没修的“陈年小疤”。
好在它终于被翻出来了。等它上线那天,X.getBar().hashCode()这种代码,终于能一键加检查了。