为什么Google Guava Preconditions的checkArgument没有返回值?

Pet*_*iuk 6 java argument-passing guava

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

public void methodWithNullCheck(String couldBeNull) {
    String definitelyNotNull = checkNotNull(couldBeNull);
    //...
}
Run Code Online (Sandbox Code Playgroud)

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

public void methodWithArgCheck(String couldBeEmpty) {
    checkArgument(!couldBeEmpty.isEmpty());
    String definitelyNotEmpty = couldBeEmpty;
    //...
}
Run Code Online (Sandbox Code Playgroud)

但它是可以添加方法,它可以做参数校验,如果校验成功返回一个值.以下是检查的示例以及如何实施:

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

我只是想知道是通过设计,是否值得为此提出功能请求.

编辑:@Nizet,是的,检查方法可能是笨拙的.但是,对构造函数中的null进行检查看起来非常好,并且节省了调试NPE所花费的大量时间:

public class SomeClassWithDependency {

    private final SomeDependency someDependency;

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

    //...
Run Code Online (Sandbox Code Playgroud)

编辑:接受Nizet的答案,因为我同意他的副作用和一致性推理.此外,如果你看看Xaerxess的评论,它看起来也会引起其他开发者的混淆.

Lou*_*man 24

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

public Foo(Bar bar) {
  this.bar = checkNotNull(bar);
}
Run Code Online (Sandbox Code Playgroud)

但是checkArgument没有做类似的事情的主要原因是你必须分别传递参数,并且它似乎不值得 - 特别是对于更复杂的前置条件检查,有时候它们的可读性更高自己的路线.只是因为某些东西可以是单行并不意味着它应该是,如果它不会增加可读性.

  • 我不知道它确实返回参数...做一个"Code Golf"重构:-) (2认同)

JB *_*zet 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()
}
Run Code Online (Sandbox Code Playgroud)

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

我看到的唯一优点是你可以做类似的事情,但我发现它比在两行单独的行中进行的可读性更差:

public String trim(String bar) {
    return Preconditions.checkNotNull(bar).trim();
}
Run Code Online (Sandbox Code Playgroud)

所以,简而言之,我同意你的观点,API 有点不一致,但我更希望所有方法都返回 void。方法应该要么有副作用,要么返回某些内容,但通常应该避免同时执行这两种操作。在这里,该方法的目标是产生副作用:抛出异常。

编辑:

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

  • 我不会做像“Preconditions.checkNotNull(bar).trim()”这样的事情,而不是简单的“bar.trim()”。在这两种情况下,你都会得到相同的 NPE,因此测试不会给你带来任何好处,你只是掩盖了一件简单的事情。`checkNotNull` 旨在快速失败,因此您可以避免方法可能不正确的部分执行并获得更短的堆栈跟踪。 (5认同)