簡體   English   中英

這個不必要的方法參考背后的想法是什么?

[英]what is the idea behind this unnecessary method reference?

java 8中的Predicate接口有一個靜態方法,如:

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為null我返回true ...完成! 或者我在幕后錯過了一些陷阱......?

該方法需要返回Predicate<T> 盡管null Predicate<T>的有效值,但在這種情況下它並不是真正有用。

如果傳入的對象為null,我們如何確定其他東西是否等於它? 好吧,我們檢查“其他東西”是否也是空的! 代碼可能是:

object -> object == null

看看這是一個lambda表達式,而不是null文字? 如果你想說“檢查某些東西是否為空”,你應該寫一個這樣的lambda表達式,而不是null

Objects::isNull方法與上面的lambda大致相同。 他們之所以選擇Objects::isNull是因為它更具可讀性。

編輯:我看到你編輯了你的問題並將null更改為true 這也不正確。

首先, true不是Predicate<T>的有效值。 如果你想要一個總是返回true的謂詞,你需要

obj -> true

無論如何,這在邏輯上也是不正確的。 null對象並不總是等於另一個對象。

我認為這里的誤解是不測試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,測試提供列表的每個元素並打印它。 此代碼還表明,如果您需要一些靈活性,謂詞和功能接口是您的朋友。 如果您的項目不需要這種靈活性,您可以安全地決定不使用它們並使用眾所周知的方法來測試您的參數。

如果要測試的對象等於引用對象,則該方法應返回一個謂詞,該謂詞的結果為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);
}

返回兩個函數中的任何一個,一個函數只測試null或函數調用equals而不測試null ,具體取決於targetRef是否為null

這也相當於

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

但是,目前還不清楚為什么JRE開發人員決定混合使用方法引用和lambda表達式...

方法Javadoc指出:

返回一個謂詞,根據Objects.equals(Object,Object)測試兩個參數是否相等。

如果null == targetRef ,則(對於另一個Object o )如果(且僅當) o == null ,則Objects.equals(targetRef, o)為真。

除此之外,你的代碼甚至不會編譯,因為true不是謂詞。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM