

若是你依然用 Java 开垦有段本事了,那你的代码库里很可能到处齐是这个短句:!= null。
if (user != null) {
sendEmail(user);
}是不是很眼熟?
乍一看没什么问题,但我想问问你:
• 万一你漏掉了一个 != null 查抄如何办?• 若是你团队里的多个开垦者对 != null 查抄的款式不一致如何办?• 这种款式会不会偷偷引入 bug ?我写 Java 代码依然十多年了,有一个资格是我付出了很大代价才学到的:
❗️ 到处写 != null 根底不是什么战略 —— 这仅仅一种细巧性的勉强作念法,频频会粉饰策画和疏导中更深头绪的问题。
在本文中,咱们将探讨:
• 为什么到处写 != null 是代码异味• 空值查抄在实践开垦中的风险• 处置 Java 中“值不存在”的更贤慧款式(附示例)• 什么本事使用 null 其实是合理的• 能让代码更易读、更可靠的最好扩充为什么咱们总在写 != null ?原因很粗拙:Java 允许空援用,而咱们齐褊狭阿谁可怕的 NullPointerException。是以咱们就像买保障相通,到处加上 != null 查抄。
if (order != null && order.getCustomer != null) {
System.out.println(order.getCustomer.getName);
}这被称为细巧性编程。天然看起来很安全,但很容易失控。
到处写 != null 果然凿问题让咱们来聊聊为什么这是一种不好的扩充:
1. 它粉饰了倒霉的策画若是你的对象在职何本事齐可能为 null,问问我方:它们为什么会是 null ?
是数据缺失了?如故从未开动化过?或是半途被删除了?
示例:
User user = userService.getUserById(id);
if (user != null) {
process(user);
}咱们莫得去引诱用户为什么可能为 null,而是跳过了这个更深头绪的问题,仅仅粗拙地“细巧”它。
{jz:field.toptypename/}2. 容易出错你越依赖 != null,就越有可能在某个处所漏掉一次查抄。你知谈这意味着什么吗?
运行时会抛出 NullPointerException。
更糟的是,这可能会在坐褥环境中特定条款下发生,而日记频频不会告诉你原因。
示例:
// 有东谈主在这里漏掉了空值查抄
order.getCustomer.getName; // 崩溃3. 让代码难以阅读多半的空值查抄会产生冗长、嵌套、难以引诱的逻辑。
if (invoice != null) {
if (invoice.getAmount != null) {
if (invoice.getAmount.compareTo(BigDecimal.ZERO) > 0) {
processInvoice(invoice);
}
}
}这么的代码可读性高吗?其实否则。
处置 Java 中 null 的更贤慧款式当今,让咱们来望望那些比到处写 != null 更贤慧、更直快的替代决策。
1. 熟习使用 OptionalJava 8 引入了 Optional —— 一个可能包含或不包含非 null 值的容器对象。
Optional userOpt = userService.findUserById(id);
userOpt.ifPresent(this::processUser);这迫使开垦者以结构化的款式处置值的缺失。
为什么更好:
• 让值的缺失变得明确,而非隐含• 幸免随机的 null• 复古函数式编程常见失误:不要在不查抄的情况下使用 Optional.get:
// 有风险
User user = userOpt.get; // 若是为空,会抛出 NoSuchElementException更安全的款式:
User user = userOpt.orElse(new GuestUser);使用 map 和 flatMap 更优:
String name = userOpt.map(User::getName)
.orElse("Unknown");2. 使用从不复返 null 的对象策画你的活动,让它们从不复返 null。相背,复返:
• 空聚拢(Collections.emptyList)• Optional 值(Optional.empty)• 极度对象,如 GuestUser、NullOrder 等示例:
// ❌ 有风险 —— 活动可能复返 null,迭代时会导致 NPE
List products = productService.getAll; // 不成保证安全
// 更好 —— 用 Optional 包装它以防护 null(若是不细目)
List products = Optional.ofNullable(productService.getAll)
.orElse(Collections.emptyList);
// 最好 —— 确保 getAll 被达成为从不复返 null
// 里面达成:若是没稀薄据,复返 Collections.emptyList
List products = productService.getAll; // 保证安全当今你的代码不错更直快:
for (Product p : products) {
display(p);
}3. 遴荐空对象模式(Null Object Pattern)有本事,与其复返 null,不如复返一个能安全运行的臆造对象。
示例:
public class GuestUser extends User {
public String getName {
return "Guest";
}
public boolean isAuthenticated {
return false;
}
}当今:
User user = userService.getOrGuest(id);
System.out.println(user.getName);这幸免了空值查抄,让代码天然绽开。
4. 快速失败 —— 而非延长失败与其将 null 向下传递并在之后查抄,不如在数据缺失机快速失败。
示例:
public void processUser(User user) {
Objects.requireNonNull(user, "User must not be null");
// 当今不错安全地使用 user 了
}这么若是出现问题,会立即抛出明晰的失误信息,而不是在之后导致难以引诱的故障。
5. 使用注解:@NonNull、@Nullable使用 @NonNull、@Nullable 等注解,并成就 Lombok、SpotBugs 或 IntelliJ 等用具,在编译时发出告诫。
示例:
public void sendEmail(@NonNull User user) {
// 若是有东谈主传递 null,编译器会报错
}这让你的代码自我文档化,况且用具会匡助你尽早发现失误。
实践重构:之前 vs 之后让咱们重构一段充满空值查抄的典型代码。
之前:
if (order != null) {
Customer c = order.getCustomer;
if (c != null && c.getEmail != null) {
sendEmail(c.getEmail);
}
}之后(使用 Optional + 快速失败):
public void processOrder(Order order) {
Objects.requireNonNull(order, "Order cannot be null");
Optional.ofNullable(order.getCustomer)
.map(Customer::getEmail)
.ifPresent(this::sendEmail);
}更直快、更安全、更易于着重。
什么本事 null 其实是合理的说真话 —— 有本事 null 是没问题的。
示例:
• 框架回调(举例 Spring 的 @Nullable)• 性能要蹊径径(幸免对象创建)• 你无规则矩的留传 API但即便如斯,你也应该:
• 收尾 null 的使用鸿沟• 明晰地文档化• 幸免在内行 API 中浮现 null给团队的更理智的 null 战略与其盲目地写 != null,不如商量以下决策树:
(此处将夸耀放大图像)
追忆null 本人并非激流猛兽,但咱们过度使用 != null 所有是一个危急信号。
以下是编写 Java 代码的更理智款式:
• 使用 Optional 默示值的缺失• 使用空对象模式幸免 null 值• 复返空聚拢而非 null• 使用 Objects.requireNonNull 快速失败• 使用注解传达预期• 冉冉重构现存代码想考咱们无法完全摒除 null —— 它们是 Java 基因的一部分。但咱们不错轨则它们。
通过解脱重叠的 != null 查抄,咱们脱手编写更直快、更安全、更具抒发力的 Java 代码 —— 这些代码读起来像故事,运行起来也相宜预期。
家长朋友们可能因为经济的因素,或是认为听力损失太重的一侧耳,助听器已经提供不了什...
在数字化波澜席卷环球的今天,个东谈主信息的传播速率和范围达到了前所未有的高度。一...
宏润竖立集团股份有限公司(以下简称“公司”)于2026年1月23日在宏润大厦会议...
科技日报记者崔爽 近日,中国科学院工程热物理接洽所自主研制的“彩色”金属3D打印...