写 Java 的朋友,谁没被 NullPointerException(空指针异常)坑过啊?可能前一天代码还跑得好好的,第二天一上线就报红,定位半天发现是某个对象突然成了 null,调用方法的时候直接崩了 —— 这种 “明明没改相关代码却出问题” 的情况,是不是特别让人抓狂?

小索奇之前帮同事排查过一个空指针问题,印象特别深:他写了个获取用户地址的方法,里面用 user.getAddress ().getCity (),平时用户都有地址信息,结果某天来了个新注册用户没填地址,address 直接是 null,一调用 getCity () 就报错,整个订单流程都卡住了。其实这种问题只要提前做个判断就能避免,但很多新手容易忽略 “对象可能为 null” 的情况,今天就跟你掰扯掰扯 Java 里空指针的 3 个高频场景,以及怎么从根源上避开。

第一个高频场景:直接调用 null 对象的方法或属性。就像刚才说的 user.getAddress ().getCity (),这种 “链式调用” 看着简洁,但只要中间任何一个对象是 null,就会触发空指针。比如 user 是 null,或者 address 是 null,甚至 city 本身是 null(如果后续有字符串操作,比如 city.length ()),都可能出问题。

很多人习惯用 if-else 判断,比如:

if (user != null) {

Address address = user.getAddress ();

if (address != null) {

String city = address.getCity ();

if (city != null) {

// 业务逻辑

}

}

}

虽然能解决问题,但嵌套太多,看着像 “if 地狱”,代码可读性特别差。小索奇更推荐用 Java 8 之后的 Optional 类,把链式调用改成 Optional 的流式处理,比如:

Optional.ofNullable (user)

.map (User::getAddress)

.map (Address::getCity)

.ifPresent (city -> {

// 业务逻辑,这里 city 一定不为 null

});

这样既避免了嵌套,又能确保每个步骤都处理了 null 的情况,代码还更简洁,是不是比一堆 if 舒服多了?

第二个高频场景:自动拆箱 null 的包装类。比如你定义了 Integer num = null,然后写 int result = num; 这时候就会触发自动拆箱,把 Integer 转成 int,但 num 是 null,没法拆箱,直接报空指针。这种问题特别隐蔽,因为编译的时候不会报错,只有运行到这行代码才会暴露。

小索奇见过有人在数据库查询的时候踩这个坑:比如数据库里某个字段允许为 null,用 MyBatis 映射成 Integer 类型,结果后续代码里直接用 int 接收,当数据库里该字段为 null 时,就会触发拆箱异常。解决方法也简单:要么在映射的时候给默认值(比如用 MyBatis 的 ifnull 函数,把 null 改成 0),要么在代码里用 Optional 处理包装类,比如 Optional.ofNullable (num).orElse (0),把 null 转成默认值再拆箱。

第三个高频场景:集合或数组里存了 null 元素,遍历的时候没处理。比如你创建了一个 List list = Arrays.asList ("a", null, "c"),然后遍历的时候直接调用 list.get (i).length (),当 i=1 的时候,元素是 null,调用 length () 就会报错。很多新手觉得 “集合里存的都是有效数据”,但实际开发中,比如从接口获取数据、从 Excel 读取内容,都可能出现 null 元素。

怎么避免呢?小索奇建议在往集合里存数据的时候就做过滤,比如用 Stream 的 filter 方法把 null 去掉:

List validList = list.stream ()

.filter (Objects::nonNull) // 过滤掉 null 元素

.collect (Collectors.toList ());

这样后续遍历的时候,就不用担心遇到 null 元素了。另外,尽量避免在集合里存 null,比如返回集合的方法,别直接返回 null,而是返回空集合(比如 Collections.emptyList ()),这样调用方就不用判断集合是否为 null,直接遍历就行。

除了这三个场景,还有个小细节要注意:字符串比较的时候,别用 null 对象调用 equals 方法。比如 String str = null; if (str.equals ("test")) { ... },这样肯定会报空指针。正确的做法是把常量放前面,比如 if ("test".equals (str)) { ... },就算 str 是 null,equals 方法也会返回 false,不会报错 —— 这个小技巧虽然简单,但能避免很多不必要的空指针。

其实 Java 空指针不是洪水猛兽,关键是养成 “凡事多问一句:这个对象会不会是 null?” 的习惯。小索奇觉得,写代码的时候多做一步 null 判断,比上线后排查空指针问题省太多时间了。毕竟排查异常可能要翻日志、定位代码、改完再重新部署,而提前处理只要多写几行代码,性价比高多了,对吧?

我是【即兴小索奇】,点击关注,后台回复 领取,获取更多相关资源

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐