拜托!别再滥用 != null 判空了!!

396 阅读4分钟

兄弟们,今天咱来聊个让小寡妇们听了都直摇头的问题:滥用 != null 判空。别觉得这是小菜一碟,多少大佬程序员踩过这坑。每次 code review,看着一堆 != null,我这暴脾气就上来了。这种码农习惯啊,咱得治!

为啥滥用 != null 是个坑

你还记得你第一次写 Java 代码吗?那时候,每次调用一个方法,你都会写上 if (something != null)。老实说,这习惯就跟小时候写作文一样,开头必写“一个风和日丽的早晨”,死板得很。滥用 != null,不光让代码看着冗长,还容易藏 BUG。想想你那几十行的 if-else 判空,谁能一眼看出问题?

Optional 来拯救世界

Java 8 给咱们带来了个神器——Optional。啥意思呢?就是咱们可以用 Optional 来包装那些可能为 null 的对象,不再需要满世界写判空。

举个栗子:

// 没用 Optional 前的老方法
public String getName(Person person) {
    if (person != null) {
        return person.getName();
    } else {
        return "Unknown";
    }
}

换成 Optional 之后:

import java.util.Optional;

public String getName(Person person) {
    return Optional.ofNullable(person)
                   .map(Person::getName)
                   .orElse("Unknown");
}

瞅瞅,是不是简洁多了?

少返回 null,多抛异常

有时候,咱们的确需要处理异常情况。很多初中级程序员喜欢返回 null 来表示异常情况。这其实是个坏习惯,应该多抛异常,少返回 null。为啥?因为 null 会让你的代码变得更脆弱,增加 NPE(NullPointerException)风险。

再举个栗子:

// 不推荐的返回 null 方式
public Person findPersonById(int id) {
    if (id < 0) {
        return null;
    }
    // 查找逻辑
}

// 调用时需要判空
Person person = findPersonById(-1);
if (person != null) {
    // 处理 person
}

推荐的方式是抛异常**:

// 推荐的抛异常方式
public Person findPersonById(int id) {
    if (id < 0) {
        throw new IllegalArgumentException("ID 不能小于 0");
    }
    // 查找逻辑
}

// 调用时处理异常
try {
    Person person = findPersonById(-1);
    // 处理 personcatch (IllegalArgumentException e) {
    // 处理异常
}

保护自己,别过度判空

有些程序员,不知道是不是被 NPE 吓坏了,写代码像在防贼一样,到处加判空。这样做不仅浪费时间,还让代码臃肿。关键是,你不信任你的代码,谁还敢信任?

例如:

// 滥用判空
if (obj != null && obj.getField() != null && obj.getField().getSubField() != null) {
    // 逻辑处理
}

其实,你可以通过设计让代码更健壮,减少这些判空。例如使用工厂模式确保对象不为 null,或者用 Optional 链式调用。

// 使用 Optional
Optional.ofNullable(obj)
        .map(Object::getField)
        .map(Field::getSubField)
        .ifPresent(subField -> {
            // 逻辑处理
        });

咱们再来举两个例子

深入理解一下为什么要减少 != null 判空,并学会用 Optional 和抛异常来处理特殊情况。

例子 1:处理用户输入

假设我们有个方法要处理用户输入,如果用户输入为空,我们返回一个默认值。传统方法可能会这样写:

// 传统方法,判空处理
public String processInput(String input) {
    if (input != null) {
        return input.trim();
    } else {
        return "default";
    }
}

使用 Optional 改写:

import java.util.Optional;

public String processInput(String input) {
    return Optional.ofNullable(input)
                   .map(String::trim)
                   .orElse("default");
}

瞧瞧,这一改,代码瞬间清爽了许多,不再需要繁琐的判空操作。

例子 2:获取配置参数

我们再来看一个获取配置参数的例子。通常情况下,我们会从配置文件中读取参数,如果参数不存在,我们可能会返回 null,然后在调用处进行判空处理:

// 传统方法,返回 null 并判空
public String getConfig(String key) {
    String value = configMap.get(key);
    if (value != null) {
        return value;
    } else {
        return null;
    }
}

public void useConfig() {
    String value = getConfig("someKey");
    if (value != null) {
        // 使用配置
    } else {
        // 使用默认值
    }
}

改用 Optional

import java.util.Optional;

public Optional<String> getConfig(String key) {
    return Optional.ofNullable(configMap.get(key));
}

public void useConfig() {
    String value = getConfig("someKey")
                   .orElse("defaultValue");
    // 使用配置或默认值
}

用 Optional 后,代码变得更加简洁,而且一眼就能看出逻辑,不再需要在每个调用处判空。

通过这两个例子,咱们可以看到,使用 Optional 能让代码更加简洁明了,减少了不必要的判空操作。而在一些特定场景下,抛出异常也能避免 null 值带来的潜在风险。

总结一波

兄弟们,今天咱们聊了这么多,不就是想说一件事儿:别再滥用 != null 判空了!这习惯就像穿着秋裤跳舞,碍手碍脚还丢人。

回顾一下咱们聊的几个要点:

Optional 的妙用:Java 8 给我们带来了 Optional,用它包装可能为 null 的对象,减少判空操作,让代码更简洁明了。

多抛异常,少返回 null:当遇到异常情况时,返回 null 不是好习惯。应该抛出适当的异常,这样可以提高代码的健壮性,减少潜在的 NPE 风险。

设计优雅代码,减少判空:过度判空不仅让代码臃肿,还容易埋下 BUG。通过设计模式和 Optional,可以让代码更健壮,减少不必要的判空操作。

最后,写代码也得讲究个艺术感。少点 != null 的啰嗦,多点 Optional 的优雅;少点判空的紧张,多点设计的从容。

已收录于,我的技术网站:ddkk.com 里面有,500套技术系列教程、1万+道,面试八股文、BAT面试真题、简历模版,工作经验分享、架构师成长之路,等等什么都有,欢迎收藏和转发。