まあ、すべてのOptional
またはObjects
に基づくソリューションは、明示的な注釈を持たないため、チェッカーがメソッドのセマンティクスを認識していると想定しています。
filter
はタイプを決して変更しないので、フィルタ機能のセマンティクスを理解していても、これをStream<@Nullable X>
→Stream<@NonNull X>
のトランジションとしてモデル化するチェッカーからの深いサポートが必要です。
簡単な方法は、それが要素の型変更することができますようmap
を使用することです。ここでは
Stream<@NonNull Object> s = str.filter(Objects::nonNull).map(Objects::requireNonNull);
を、フィルタ操作にはnull
要素が存在しないことを保証しますが、正式な要素の型を変更しません。対照的に、map
操作では正式タイプの変更が可能であり、関数Objects::requireNonNull
は、これらのJRE提供メソッドに注釈がないと監査ツールが認識していると仮定して、null入力を非NULL出力に変換します。
requireNonNull
はnull
値の例外をスローするので、filter
とmap
の組み合わせのみがnull
値を除去し、正式な要素タイプを変更する目的の動作を可能にします。任意の合理的で正しいとして認識されるべき
監査ツールは、JREのメソッドの意味を理解していない場合は、注釈で、その後、同等の方法を自分で作成する必要があります、
class MyObjUtil {
public static <T> @NonNull T requireNonNull(@Nullable T obj) {
if(obj==null) throw new NullPointerException();
return obj;
}
}
チェッカー、および
Stream<@NonNull Object> s = str.filter(Objects::nonNull).map(MyObjUtil::requireNonNull);
としてそれを使用するあなたのOptional
ベースのアプローチは、Java 9に簡素化することができます。
Stream<@NonNull Object> s = str.flatMap(o -> Optional.ofNullable(o).stream());
さらに簡略化することができた。
Stream<@NonNull Object> s = str.flatMap(o -> Stream.ofNullable(o));
もちろん、これは再び、これらの方法を理解するツールが必要です。それとも再実装ロジック:
class MyStreamUtil {
public static <T> Stream<@NonNull T> ofNullable(@Nullable T obj) {
return obj==null? Stream.empty(): Stream.of(obj);
}
}
Stream<@NonNull Object> s = str.flatMap(o -> MyStreamUtil.ofNullable(o));
その後、同様のJava 8の下で動作します。
'str.filter(Objects :: nonNull).map(Objects :: requireNonNull)' ... – Holger