Java 替换/改进 null 检查

Java Replace / Improve null check

我有一个伪 Java 方法,其中所有内容都可以为空:

private String prepareMessage(Scope scope) {
    if (scope != null) {
        if (scope.getPermission != null) {
            if (scope.getInfo != null) {
                return "Successful";
            } else {
                return "Missing field Info";
            }
        } else if (scope.getInfo() != null) {
            return "Permission field not provided";
        }
    }
    return "Permission and Info fields not provided";
}

如何简化此代码以删除看起来很糟糕的空检查?谢谢!

你可以创建一个适合你的辅助方法,例如:

public String notNullOrElse(Object o, String notNull, String isNull) {
    return null != o ? notNull : isNull;
}

那你可以改:

if (scope.getInfo != null) {
    return "Successful";
} else {
    return "Missing field Info";
}

至:

return notNullOrElse(scope.getInfo(), "Successfull", "Missing field Info");

然而,不幸的是,有时那些可怕的空检查是必要的。

尝试重构代码。在大多数情况下,您可以通过重新排序代码流来简化 If - else。这使得获得代码覆盖变得容易。

private String prepareMessage(Scope scope) {
    if (scope == null) {
        return "Permission and Info fields not provided";
    }

    if (scope.getPermission != null && scope.getInfo != null) {
        return "Successful";
    } else {
        return scope.getPermission == null ? "Permission field not provided" : "Missing field Info";
    }

}

该文档很好地解释了 if-else 中的代码异味 -> https://dzone.com/articles/code-smells-if-statements

Java 1.7 引入了 class java.util.Objectsthis link 来自 Java 11 Java 文档,但这应该无关紧要在这里)。

class 提供了方法 Objects.isNull()Objects.nonNull(),可以在您的代码中按如下方式使用:

import static java.util.Objects.*;
…
private String prepareMessage(Scope scope) {
    if (nonNull (scope)) {
        if (nonNull (scope.getPermission())) {
            if (nonNull (scope.getInfo())) {
                return "Successful";
            } else {
                return "Missing field Info";
            }
        } else if (nonNull (scope.getInfo()) {
            return "Permission field not provided";
        }
    }
    return "Permission and Info fields not provided";
}

当然,这是否更好看是一个品味问题。

替代逻辑可能如下所示(对于 Java 11):

import static java.util.Objects.*;
…
private String prepareMessage( Scope scope ) 
{
    var messages = { "Successful", "Missing field Info", "Permission field not provided", "Permission and Info field not provided" };
    var index = 0;
    var retValue = messages [3]; // No scope at all

    if( nonNull( scope ) ) 
    {
        if( isNull( scope.getPermission() ) ) index += 2;
        if( isNull( scope.getInfo() ) ) index += 1;
        retValue = messages [index];
    }
    return retValue;
}

我不想说这真的更好,只是不同而已。它省去了一次空检查……