我有幾個問題很難找到答案,至少在 Java 中是這樣。
我在教程中看到了一個類定義,其中 lambda 的使用類似于方法。所以我很好奇除了簡潔的代碼和風格偏好之外是否還有任何好處。
例子:
public class Blocks {
private Deque<Block> entries;
public Blocks() {
this.entries = new ArrayDeque<>();
}
public Deque<Block> getEntries() {
return entries;
}
public void setEntries(Deque<Block> entries) {
this.entries = new ArrayDeque<>(entries);
}
public Predicate<Block> push = entries::offerLast;
public Supplier<Optional<Block>> peek = () -> Optional.ofNullable(entries.peekLast());
public BooleanSupplier isEmpty = entries::isEmpty;
public Supplier<String> lastHash = () -> peek.get().map(Block::hash).orElse("0");
public LongSupplier size = entries::size;
}
這是一個有效的類定義嗎?這是一種不好的做法嗎?如果是這樣,為什么?
我注意到的一件事是在謂詞推送中,我收到以下警告:
Dereference of 'entries' will produce 'NullPointerException'
如果應該實體化條目,為什么會收到此警告?該警告似乎影響具有方法參考的任何函式。如果相反:
public Predicate<Block> push = block -> entries.offerLast(block);
然后警告消失。
uj5u.com熱心網友回復:
類的欄位初始化程式在建構式之前按文本順序運行。因此,該領域push,isEmpty等等都將被初始化之前entries在建構式初始化得到。
當一個方法參考運算式entries::offerLast被求值時,entries首先被求值以確定應該在哪個物件上呼叫該方法。但是,由于entries在計算方法參考運算式時未初始化,因此entries計算結果為 null。這會導致NullPointerException拋出 a。JLS 15.13.3
首先,如果方法參考運算式以 ExpressionName 或 Primary 開頭,則計算此子運算式。如果子運算式的計算結果為 null,則會引發 NullPointerException,并且方法參考運算式會突然完成。
要解決此問題,您可以將entires欄位的初始化移出建構式,并與其宣告行內:
private Deque<Block> entries = new ArrayDeque<>();
或者,您可以使用 lambda 運算式而不是方法參考:
public Predicate<Block> push = e -> entries.offerLast(e);
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/373447.html
