这个不必要的方法参考背后的想法是什么?
what is the idea behind this unnecessary method reference?
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
没有带来任何进一步的改进...并且稍微降低了可读性...
if is null I return true...完成!还是我错过了幕后的一些陷阱..?
该方法需要return一个Predicate<T>
。尽管 null
是 Predicate<T>
的有效值,但在这种情况下它并不是很有用。
如果传入的对象为null,我们如何判断其他对象是否等于它?好吧,我们检查 "something else" 是否也为空!代码可能是:
object -> object == null
看看这是一个 lambda 表达式,而不是 null
文字?如果你想说 "check whether something is null" 你应该写一个像这样的 lambda 表达式,而不是 null
.
Objects::isNull
方法的作用与上述 lambda 大致相同。他们选择 Objects::isNull
因为它更具可读性。
编辑:我看到您编辑了问题并将 null
更改为 true
。这也不对。
首先,true
不是 Predicate<T>
的有效值。如果您想要一个始终 return 为真的谓词,您需要
obj -> true
无论如何,这在逻辑上也是不正确的。空对象并不总是等于另一个对象。
Returns a predicate that tests if two arguments are equal according to Objects.equals(Object, Object).
如果 null == targetRef
,则(对于另一个 Object o
)如果(且仅当)o == null
.
Objects.equals(targetRef, o)
为真
除此之外,您的代码甚至无法编译,因为 true
不是谓词。
我认为这里的误解是没有测试 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
,都会构建一个谓词测试是否相等,测试所提供列表的每个元素并将打印它。
这段代码还表明,如果你需要一些灵活性,谓词和函数式接口是你的朋友。
如果您的项目不需要这种灵活性,您可以安全地决定不使用它们并使用众所周知的方法来测试您的参数。
如果要测试的对象等于引用对象,则该方法应该return 一个评估为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);
}
但是,targetRef
是否为 null
在谓词构造后不会改变,并且由于谓词可能会被评估不止一次,因此将不变属性的测试移出会更有效谓词并创建专门的谓词函数。
实现等同于
static <T> Predicate<T> isEqual(Object targetRef) {
return null == targetRef? object -> object==null: object -> targetRef.equals(object);
}
return 两个函数之一,一个函数只测试 null
或一个调用 equals
而不测试 null
的函数,这取决于 [=16] =] 是 null
.
这也等同于
static <T> Predicate<T> isEqual(Object targetRef) {
return null == targetRef? Objects::isNull: targetRef::equals;
}
但是,尚不清楚为什么 JRE 开发人员决定混合使用方法引用和 lambda 表达式……
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
没有带来任何进一步的改进...并且稍微降低了可读性...
if is null I return true...完成!还是我错过了幕后的一些陷阱..?
该方法需要return一个Predicate<T>
。尽管 null
是 Predicate<T>
的有效值,但在这种情况下它并不是很有用。
如果传入的对象为null,我们如何判断其他对象是否等于它?好吧,我们检查 "something else" 是否也为空!代码可能是:
object -> object == null
看看这是一个 lambda 表达式,而不是 null
文字?如果你想说 "check whether something is null" 你应该写一个像这样的 lambda 表达式,而不是 null
.
Objects::isNull
方法的作用与上述 lambda 大致相同。他们选择 Objects::isNull
因为它更具可读性。
编辑:我看到您编辑了问题并将 null
更改为 true
。这也不对。
首先,true
不是 Predicate<T>
的有效值。如果您想要一个始终 return 为真的谓词,您需要
obj -> true
无论如何,这在逻辑上也是不正确的。空对象并不总是等于另一个对象。
Returns a predicate that tests if two arguments are equal according to Objects.equals(Object, Object).
如果 null == targetRef
,则(对于另一个 Object o
)如果(且仅当)o == null
.
Objects.equals(targetRef, o)
为真
除此之外,您的代码甚至无法编译,因为 true
不是谓词。
我认为这里的误解是没有测试 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
,都会构建一个谓词测试是否相等,测试所提供列表的每个元素并将打印它。
这段代码还表明,如果你需要一些灵活性,谓词和函数式接口是你的朋友。
如果您的项目不需要这种灵活性,您可以安全地决定不使用它们并使用众所周知的方法来测试您的参数。
如果要测试的对象等于引用对象,则该方法应该return 一个评估为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);
}
但是,targetRef
是否为 null
在谓词构造后不会改变,并且由于谓词可能会被评估不止一次,因此将不变属性的测试移出会更有效谓词并创建专门的谓词函数。
实现等同于
static <T> Predicate<T> isEqual(Object targetRef) {
return null == targetRef? object -> object==null: object -> targetRef.equals(object);
}
return 两个函数之一,一个函数只测试 null
或一个调用 equals
而不测试 null
的函数,这取决于 [=16] =] 是 null
.
这也等同于
static <T> Predicate<T> isEqual(Object targetRef) {
return null == targetRef? Objects::isNull: targetRef::equals;
}
但是,尚不清楚为什么 JRE 开发人员决定混合使用方法引用和 lambda 表达式……