空判断怎么优化减少冗余?

访客 自然语言处理 1

本文目录导读:

  1. 使用 Optional(Java 8+ / Guava)
  2. 使用 Objects.requireNonNull / 断言(防御性编程)
  3. 使用 Apache Commons / Guava 工具类
  4. 使用 @Nullable / @NonNull 注解 + 静态分析(编译期消除)
  5. 使用空对象模式(Null Object Pattern)
  6. 使用流式 API 与 filter(Objects::nonNull)(处理集合)
  7. 对于特定语言的语法糖
  8. 总结:如何选择?

“空判断”的冗余通常指代码中反复出现 if (xxx == null || xxx.isEmpty()) 或类似检查,并且这些检查的逻辑散落在各处。

核心优化的思路是:利用语言特性、设计模式、或类型系统,将“可能为空”这个状态,在更大范围内统一处理,而不是每次都单独判断。

以下是针对不同场景的 7 种具体优化策略:

使用 Optional(Java 8+ / Guava)

对于单一对象的链式调用,避免 null 检查的瀑布嵌套。

  • 冗余代码
    if (user != null) {
        Address address = user.getAddress();
        if (address != null) {
            String city = address.getCity();
            if (city != null) {
                System.out.println(city.toUpperCase());
            }
        }
    }
  • 优化后
    Optional.ofNullable(user)
            .map(User::getAddress)
            .map(Address::getCity)
            .ifPresent(city -> System.out.println(city.toUpperCase()));

使用 Objects.requireNonNull / 断言(防御性编程)

对于方法参数,如果空值本身就是非法的,应该在入口处明确抛出异常,而不是在内部多处判断。

  • 冗余代码
    public void process(String name) {
        if (name == null) {
            throw new IllegalArgumentException("Name must not be null");
        }
        // ... 后面再也不用担心 name 为 null
    }
  • 优化后(一种写法)
    public void process(String name) {
        this.name = Objects.requireNonNull(name, "Name must not be null");
        // 或直接调用方法而无需检查
    }

使用 Apache Commons / Guava 工具类

对于字符串/集合,这些库提供了省去手动空判断的便捷方法。

  • 冗余代码
    if (list != null && list.size() > 0) {
        // 处理
    }
    if (str != null && !str.isEmpty()) {
        // 处理
    }
  • 优化后
    if (CollectionUtils.isNotEmpty(list)) {
        // 处理
    }
    if (StringUtils.isNotBlank(str)) { // 同时处理了 null 和空格
        // 处理
    }

使用 @Nullable / @NonNull 注解 + 静态分析(编译期消除)

在本地开发或代码审查阶段消灭空指针风险,运行时无需写 if 判断。

  • 做法:在方法参数或返回值上标注注解,配合 IDE 或 Lint 工具检查。
    public void setUser(@NotNull User user) {
        // IDE 会警告如果调用者传入 null
    }
    @NotNull
    public String getName() {
        return Objects.requireNonNull(name);
    }

使用空对象模式(Null Object Pattern)

对于返回值频繁为 null 的场景,返回一个无行为的默认对象,省去调用方的 null 判断。

  • 冗余代码
    Log logger = getLogger();
    if (logger != null) {
        logger.info("...");
    }
  • 优化后
    // getLogger() 返回一个实现了 Logger 接口的 NullLogger 对象
    // 内部所有方法为空实现(无操作)
    Log logger = getLogger(); // 保证不返回 null
    logger.info("..."); // 直接调用,无需判断

使用流式 API 与 filter(Objects::nonNull)(处理集合)

当你有一个集合,里面可能包含 null 元素,你需要处理非空元素时。

  • 冗余代码
    for (String s : list) {
        if (s != null) {
            // 处理 s
        }
    }
  • 优化后
    list.stream()
        .filter(Objects::nonNull)
        .forEach(s -> {
            // 处理 s
        });

对于特定语言的语法糖

  • Kotlin:利用 (安全调用) 和 (Elvis 操作符) 消除冗余。

    // 冗余写法:
    if (user != null) {
        println(user.name?.toUpperCase() ?: "UNKNOWN")
    }
    // 优化后:
    println(user?.name?.toUpperCase() ?: "UNKNOWN")
  • TypeScript / JavaScript:利用可选链 和空值合并 。

    // 冗余写法:
    const city = user && user.address && user.address.city ? user.address.city : 'Unknown';
    // 优化后:
    const city = user?.address?.city ?? 'Unknown';
  • Python:利用 or 短路或字典的 .get 方法。

    # 冗余写法:
    if config and 'key' in config and config['key'] is not None:
        value = config['key']
    else:
        value = 'default'
    # 优化后:
    value = config.get('key') or 'default'

如何选择?

场景 最佳策略
链式调用 (user.getAddr().getCity()) Optional / 可选链语法
方法参数 Objects.requireNonNull / 断言
字符串集合判空 Apache Commons / Guava 工具类
返回值可能为 null 空对象模式 / Optional
集合过滤 null 元素 流式 API + filter
整个代码库空值泛滥 引入 @NonNull 注解 + 静态分析
使用现代语言 原生语法 (Kotlin , Dart , TS )

最根本的优化不要返回 null,设计 API 时,优先返回空集合(Collections.emptyList())或空对象,而不是 null,这能从根源上减少 50% 以上的空判断。

标签: 代码冗余

抱歉,评论功能暂时关闭!