6

我真的很喜欢 guava 库如何允许简单的单行代码检查 null:

public void methodWithNullCheck(String couldBeNull) {
    String definitelyNotNull = checkNotNull(couldBeNull);
    //...
}

可悲的是,对于简单的参数检查,您至少需要两行代码:

public void methodWithArgCheck(String couldBeEmpty) {
    checkArgument(!couldBeEmpty.isEmpty());
    String definitelyNotEmpty = couldBeEmpty;
    //...
}

但是,可以添加可以进行参数检查在检查成功时返回值的方法。以下是检查的示例以及如何实施:

public void methodWithEnhancedArgCheck(String couldBeEmpty) {
    String definitelyNotEmpty = EnhancedPreconditions.checkArgument(couldBeEmpty, !couldBeEmpty.isEmpty());
    //...
}

static class EnhancedPreconditions {
    public static <T> T checkArgument(T reference, boolean expression) {
        if (!expression) {
            throw new IllegalArgumentException();
        }

        return reference;
    }
}

我只是想知道这是设计使然,是否值得为此提出功能要求。

编辑:@Nizet,是的,检查方法可能很笨拙。但是在构造函数中检查空值看起来非常好,并且可以节省大量用于调试 NPE 的时间:

public class SomeClassWithDependency {

    private final SomeDependency someDependency;

    public SomeClassWithDependency(SomeDependency someDependency) {
        this.someDependency = checkNotNull(someDependency);
    }

    //...

编辑:接受 Nizet 的回答,因为我同意他的副作用和一致性推理。此外,如果您查看 Xaerxess 评论,它看起来也会在其他开发人员中引起混淆。

4

3 回答 3

24

返回其参数的最大单一原因checkNotNull是它可以在构造函数中使用,如下所示:

public Foo(Bar bar) {
  this.bar = checkNotNull(bar);
}

checkArgument但是不做类似事情的主要原因是无论如何你都必须单独传递参数,而且这似乎不值得——尤其是使用更复杂的前置条件检查,有时在他们的自己的线。仅仅因为某些东西可以是单行的,并不意味着它应该是,如果它不增加可读性的话。

于 2012-07-29T14:05:54.663 回答
2

我从来不明白为什么checkNotNull()首先返回它的论点:

public void foo(String bar) {
    Preconditions.checkNotNull(bar);
    // here, you're sure that bar is not null. 
    // No need to use another variable or to reassign bar to the result 
    // of checkNotNull()
}

checkNotNull()如上所述,我个人忽略 的结果。这使得事情与其他返回无效的检查一致。

我看到的唯一优点是您可以执行类似的操作,但我发现它的可读性不如在两个单独的行中执行:

public String trim(String bar) {
    return Preconditions.checkNotNull(bar).trim();
}

所以,简而言之,我同意你的观点,API 有点不一致,但我希望所有方法都返回 void。一个方法应该要么有副作用,要么返回一些东西,但通常应该避免两者都做。在这里,该方法的目标是产生副作用:抛出异常。

编辑:

您的示例确实是对为什么返回参数有用的更有效的解释。但我仍然倾向于一致性和清洁性,而不是这种在一行中检查和分配的可能性。

于 2012-07-29T12:48:04.280 回答
1

您可以将 valid4j 与 hamcrest-matchers 一起使用(在 Maven Central 上以 org.valid4j:valid4j 的形式找到)

对于前置条件和后置条件:

import static org.valid4j.Assertive.*;

this.myField = require(argument, notNullValue());
this.myInteger = require(x, greaterThan(0));
...
return ensure(result, isValid());

对于输入验证:

import static org.valid4j.Validation.*;


validate(argument, isValid(), otherwiseThrowing(InvalidException.class));

链接:

于 2014-11-30T23:40:05.543 回答