2016-01-21 2 views
5

これはバグですか?以下はjava 8オプションmap()はファンクションリファレンス付きのNPEを投げますが、完全なラムダ構文では使用しません

は、例えばNPE

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

でもない

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

のIntelliJで失敗今まで、私には意味をなさ同等として最初のもの、ことにより、第2の表現を交換することをお勧め。

この現象の理由は、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)); 
    } 
} 

map()を用いて実装された場合:

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

は、我々は最初の2つのスニペットの間で一貫性のある動作になるだろう。 map()が2番目の実装ではない理由は何ですか?

答えて

7

明示的に文書化されているため、これはバグではありません。 Optional.map(mapper) Javadocの引用:

値が存在する場合

は、それに設けられたマッピング関数を適用する[...]
...

例外:

NullPointerException - もしマッピング機能はnull

ですので、 nullmapperである場合、値の有無にかかわらず、常にNullPointerExceptionがスローされます。これは最初のケースで例外を説明しています。ただし、マッパーは値がある場合にのみ適用されます。これは、2番目のケースで例外がない理由を説明しています。

+0

良いキャッチ。関数が実際に呼び出された場合にのみヌル関数をチェックするのはなぜですか? – matthieus

+1

@matthieus私は恐れるとは言いません。これについてOpenJDKのメーリングリストのメールを見つけることができませんでした(これは主に意見に基づいています)。 – Tunaki

+3

実際、['orElseGet'](https://docs.oracle.com/javase/8/docs/api/java/util/Optional.html#orElseGet-java.util.function.Supplier-)が動作するのは本当に奇妙ですサプライヤがnull *かつ* valueが存在しない場合に限り、NPEをスローします。 Paul Sandoz [http://mail.openjdk.java.net/pipermail/core-libs-dev/2015-September/035426.html]は、誤ってorElseGetの指定がこのように行われたことを示しています。 –

関連する問題