2016-01-21 11 views
5

Czy to błąd lub funkcja?java 8 Opcjonalna mapa() rzut NPE z odniesieniem do funkcji, ale nie z pełną składnią lambda

Poniżej powiedzie się z NPE

Function<String, String> f = null; 
Optional.<String>empty().map(f).orElse(null); 

Ale nie

Function<String, String> f = null; 
Optional.<String>empty().map(value -> f.apply(value)).orElse(null); 

IntelliJ na przykład sugerowałaby zastąpić drugie wyrażenie przez pierwszy za równoważne, co dla mnie sens, aż do teraz.

Powodem takiego zachowania jest realizacja 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)); 
    } 
} 

Zamiast tego, jeśli map() został zrealizowany przy:

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)); 
    } 
} 

chcemy uzyskać spójne zachowanie między 2 pierwszych fragmentów. Każdy powód, dla którego map() nie jest drugą implementacją?

Odpowiedz

7

To nie jest błąd, ponieważ jest wyraźnie udokumentowany. Cytowanie Optional.map(mapper) Javadoc:

Jeśli wartość nie jest obecny, zastosować podaną funkcję mapowania do niej [...]
...

Zgłasza:

NullPointerException - jeśli funkcja mapowania to null

Tak więc metoda zawsze wyrzuć NullPointerException, niezależnie od obecności wartości lub nie, jeśli podana mapper jest null: to wyjaśnia wyjątek w pierwszym przypadku. Jednak program odwzorowujący jest stosowany tylko wtedy, gdy istnieje wartość: to wyjaśnia, dlaczego w drugim przypadku nie ma wyjątku.

+0

Dobry połów. Każdy pomysł, dlaczego nie sprawdzanie funkcji null tylko wtedy, gdy funkcja jest rzeczywiście wywoływana? – matthieus

+1

@matthieus Obawiam się, że nie mogę powiedzieć. Nie mogłem znaleźć żadnej wiadomości z listy dyskusyjnej OpenJDK na ten temat (jest to najprawdopodobniej oparte na opiniach). – Tunaki

+3

Właściwie to jest naprawdę dziwne, że działa ['orElseGet'] (https://docs.oracle.com/javase/8/docs/api/java/util/Optional.html#orElseGet-java.util.function.Supplier-) w inny sposób: rzuca NPE tylko wtedy, gdy dostawca ma wartość null * i * nie ma wartości. Paul Sandoz [uzgodniony] (http://mail.openjdk.java.net/pipermail/core-libs-dev/2015-September/035426.html) że omawiana specyfikacja 'orElseGet' została wykonana w ten sposób przez pomyłkę. –

Powiązane problemy