这个不必要的方法参考背后的想法是什么?

时间:2017-09-19 06:08:40

标签: java methods java-8 predicate

java 8中的Predicate interface有一个静态方法,如:

static <T> Predicate<T> isEqual(Object targetRef) {
    return (null == targetRef)
            ? Objects::isNull
            : object -> targetRef.equals(object);
}

为什么不这样做:

 return (null == targetRef) 
            ? null
            : object -> targetRef.equals(object);

我的意思是,这个方法参考Objects::isNull没有带来任何进一步的改进......并且正在减少一点可读性......

如果为null我返回true ...完成!或者我在幕后错过了一些陷阱......?

4 个答案:

答案 0 :(得分:8)

该方法需要返回Predicate<T>。虽然null 是<{1}}的有效值,但在这种情况下它并非真正有用。

如果传入的对象为null,我们如何确定其他东西是否等于它?那么,我们检查一下&#34;其他什么&#34;也是空的!代码可能是:

Predicate<T>

看看这是一个lambda表达式,而不是object -> object == null 字面值?如果你想说&#34;检查某些东西是否为空&#34;你应该写一个像这样的lambda表达式,而不是null

null方法与上面的lambda大致相同。他们之所以选择Objects::isNull,是因为它更具可读性。

编辑:我看到您修改了问题并将Objects::isNull更改为null。这也不正确。

首先,true不是true的有效值。如果你想要一个总是返回true的谓词,你需要

Predicate<T>

无论如何,这在逻辑上也是不正确的。 null对象并不总是等于另一个对象。

答案 1 :(得分:5)

我认为这里的误解是没有测试targetRef是否为null,但是这个方法返回一个测试相等的Predicate(一个函数)。

所以这样的代码可以写成:

Predicate<String> writtenByAuthor = Predicate.isEqual("Firewall-Alien");

此实例可以在使用谓词的其他方法中使用,例如java.util.stream.Stream.filter(Predicate<? super T> p)

回到你关于null的问题,这个片段可能会说明用法:

void printMatching(List<String> list, String s) {
   printMatching(list, Predicate.isEqual(s));
}

void printMatching(List<String> list, Predicate<? super String> filter) {
   Objects.requireNonNull(list);
   Objects.requireNonNull(filter);
   list.stream().filter(filter).forEach(System.out::println);
}   

现在查看此代码,无论s是否为null,都会构建一个测试相等性的Predicate,测试提供列表的每个元素并打印它。 这段代码还表明,如果你需要一些灵活性谓词和功能界面是你的朋友。 如果您的项目不需要这种灵活性,您可以放心地决定不使用它们并使用众所周知的方法来测试您的参数。

答案 2 :(得分:4)

如果要测试的对象等于参考对象,则该方法应返回一个评估为true的谓词,以null安全方式检查。

它可以像

一样实现
static <T> Predicate<T> isEqual(Object targetRef) {
    return object -> Objects.equals(object, targetRef);
}

相当于

static <T> Predicate<T> isEqual(Object targetRef) {
    return object -> object==targetRef || targetRef!=null&&targetRef.equals(object);
}

但是,targetRefnull是否在谓词构造之后不会改变,并且因为谓词可能不止一次被评估,所以将不变属性的测试移出谓词并创建专门的谓词函数。

实施等同于

static <T> Predicate<T> isEqual(Object targetRef) {
    return null == targetRef? object -> object==null: object -> targetRef.equals(object);
}

返回两个函数中的任何一个,仅测试null的函数或调用equals的函数而不测试null,具体取决于targetRefnull }。

这也等同于

static <T> Predicate<T> isEqual(Object targetRef) {
    return null == targetRef? Objects::isNull: targetRef::equals;
}

然而,目前还不清楚为什么JRE开发人员决定混合使用方法引用和lambda表达式......

答案 3 :(得分:3)

Javadoc of that method州:

  

返回一个谓词,根据Objects.equals(Object,Object)测试两个参数是否相等。

如果null == targetRef,那么(对于另一个Object oObjects.equals(targetRef, o)如果(且仅限于)o == null则为真。

除此之外,您的代码甚至无法编译,因为true不是谓词。