2016-01-21 6 views
5

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?

Antwort

7

Dies ist kein Fehler, weil es explizit dokumentiert ist. Zitiert Optional.map(mapper) Javadoc:

Wenn ein Wert vorhanden ist, gelten die bereitgestellte Abbildungsfunktion, um es [...]
...

Würfe:

NullPointerException - wenn die Abbildungsfunktion ist null

So ist die map Methode immer eine NullPointerException werfen, unabhängig von dem Vorhandensein eines Wertes oder nicht, wenn die mapper gegeben ist null: Dies erklärt die Ausnahme im ersten Fall. Der Mapper wird jedoch nur angewendet, wenn ein Wert vorhanden ist. Dies erklärt, warum im zweiten Fall keine Ausnahme vorliegt.

+0

Guter Fang. Jede Idee, warum nicht nur nach einer Nullfunktion suchen, wenn die Funktion tatsächlich aufgerufen wird? – matthieus

+1

@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

+3

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. –

Verwandte Themen