Ist das ein Fehler oder eine Funktion?java 8 Optional map() NPE mit Funktionsreferenz, aber nicht mit voller Lambdasyntax werfen
nicht Below mit NPE
Function<String, String> f = null;
Optional.<String>empty().map(f).orElse(null);
Aber nicht
Function<String, String> f = null;
Optional.<String>empty().map(value -> f.apply(value)).orElse(null);
IntelliJ zum Beispiel würde vorschlagen, den zweiten Ausdruck durch die ersten als gleichwertig zu ersetzen, die für mich Sinn gemacht, bis jetzt.
Der Grund für dieses Verhalten ist die Implementierung von Optional#map()
:
public<U> Optional<U> map(Function<? super T, ? extends U> mapper) {
// check happens before the branching
Objects.requireNonNull(mapper);
if (!isPresent())
return empty();
else {
return Optional.ofNullable(mapper.apply(value));
}
}
Stattdessen, wenn map()
mit umgesetzt wurde:
public<U> Optional<U> map(Function<? super T, ? extends U> mapper) {
if (!isPresent())
return empty();
else {
// the check happens only when relevant
Objects.requireNonNull(mapper);
return Optional.ofNullable(mapper.apply(value));
}
}
wir ein konsistentes Verhalten zwischen dem ersten 2 Schnipsel bekommen würden. Irgendein Grund, warum map()
nicht die zweite Implementierung ist?
Guter Fang. Jede Idee, warum nicht nur nach einer Nullfunktion suchen, wenn die Funktion tatsächlich aufgerufen wird? – matthieus
@matthieus Das kann ich leider nicht sagen. Ich konnte keine Mail von der OpenJDK-Mailing-Liste darüber finden (es ist höchstwahrscheinlich meinungsbasiert). – Tunaki
Eigentlich ist es wirklich komisch, dass ['orElseGet'] (https://docs.oracle.com/javase/8/docs/api/java/util/Optional.html#orElseGet-java.util.function.Supplier-) funktioniert auf andere Weise: NPE wird nur ausgelöst, wenn der Lieferant null ist * und * value nicht vorhanden ist. Paul Sandoz [stimmte zu] (http://mail.openjdk.java.net/pipermail/core-libs-dev/2015-September/035426.html), dass die "orElseGet" -Spezifikation irrtümlicherweise auf diese Weise gemacht wurde. –