Optional
Javaに追加された理由は次のとおりです。
return Arrays.asList(enclosingInfo.getEnclosingClass().getDeclaredMethods())
.stream()
.filter(m -> Objects.equals(m.getName(), enclosingInfo.getName())
.filter(m -> Arrays.equals(m.getParameterTypes(), parameterClasses))
.filter(m -> Objects.equals(m.getReturnType(), returnType))
.findFirst()
.getOrThrow(() -> new InternalError(...));
これよりもきれいです:
Method matching =
Arrays.asList(enclosingInfo.getEnclosingClass().getDeclaredMethods())
.stream()
.filter(m -> Objects.equals(m.getName(), enclosingInfo.getName())
.filter(m -> Arrays.equals(m.getParameterTypes(), parameterClasses))
.filter(m -> Objects.equals(m.getReturnType(), returnType))
.getFirst();
if (matching == null)
throw new InternalError("Enclosing method not found");
return matching;
私のポイントは、オプションが Javaに同時に追加された関数型プログラミングをサポートするように作成されたことです。(この例は、Brian Goetzのブログの厚意により提供されています。orElse()
このコードはとにかく例外をスローするため、この方法を使用するより良い例ですが、画像を取得します。)
しかし今、人々は非常に異なる理由でオプションを使用しています。彼らは、言語設計の欠陥に対処するためにそれを使用しています。欠点はこれです:どのAPIのパラメーターと戻り値をnullにできるかを指定する方法はありません。それはjavadocsで言及されているかもしれませんが、ほとんどの開発者は自分のコード用のjavadocを書くことすらしていません。したがって、これにより、多くのコードが使用前に常にnull値をチェックします。ただし、呼び出しスタックですでに9回または10回繰り返し検証されているため、nullになることはほとんどありません。
新しいOptionalクラスがその目的をAPIを明確にすることであると想定していた多くの人々が、この欠陥を解決するための本当の渇きがあったと思います。人々が「ゲッターはオプションを返すべきですか?」いいえ、ゲッターが関数型プログラミングで使用されることを期待している場合を除き、おそらく使用すべきではありません。実際、Java APIでOptionalが使用されている場所を見ると、これは主に関数型プログラミングのコアであるStreamクラスにあります。(私は徹底的にチェックしていませんが、Streamクラスが使用される唯一の場所かもしれません。)
少し関数コードでゲッターを使用する予定がある場合は、標準のゲッターとOptionalを返す2番目のゲッターを用意することをお勧めします。
ああ、クラスをシリアル化可能にする必要がある場合は、絶対にOptionalを使用しないでください。
オプションは、a)非常に冗長であり、b)最初からその問題を解決することを意図していないため、APIの欠陥に対する非常に悪いソリューションです。
APIの欠陥に対するはるかに優れた解決策はNullness Checkerです。これは、@ Nullableで注釈を付けることにより、nullにできるパラメーターと戻り値を指定できる注釈プロセッサーです。このようにして、コンパイラーはコードをスキャンして、実際にnullになる可能性のある値がnullが許可されていない値に渡されているかどうかを判断できます。デフォルトでは、注釈が付けられていない限り、nullにすることは許可されていません。これにより、null値を気にする必要がなくなります。パラメータにnull値を渡すと、コンパイラエラーが発生します。nullにできないnullのオブジェクトをテストすると、コンパイラ警告が生成されます。これの効果は、NullPointerExceptionを実行時エラーからコンパイル時エラーに変更することです。
これはすべてを変えます。
ゲッターについては、オプションを使用しないでください。そして、どのメンバーもnullにならないようにクラスを設計してください。Nullness Checkerをプロジェクトに追加して、必要に応じてゲッターとセッターのパラメーター@Nullableを宣言してみてください。私はこれを新しいプロジェクトでのみ行いました。おそらく、nullに関する多くの余分なテストで記述された既存のプロジェクトで多くの警告が生成されるため、改造するのは難しいかもしれません。しかし、それはまた多くのバグをキャッチします。大好きです。そのため、私のコードはよりクリーンで信頼性が高くなっています。
(これに対処する新しい言語もあります。JavaバイトコードにコンパイルされるKotlinを使用すると、オブジェクトを宣言するときにオブジェクトがnullであるかどうかを指定できます。よりクリーンなアプローチです。)
元の投稿への補遺(バージョン2)
多くのことを考えた後、しぶしぶと、1つの条件でOptionalを返すことは許容できるという結論に達しました。つまり、取得した値が実際にはnullである可能性があります。nullを返すことができないゲッターからOptionalを日常的に返すコードをたくさん見ました。私はこれを、コードに複雑さを追加するだけの非常に悪いコーディング慣行と見なしています。しかし、戻り値が実際にはnullである可能性がある場合は、先に進んでそれをOptional内にラップします。
関数型プログラミング用に設計され、関数参照が必要なメソッドは、2つの形式で記述される必要があり、その1つはOptionalを使用することに注意してください。例えば、Optional.map()
およびOptional.flatMap()
両方のテイク関数参照。最初は通常のゲッターへの参照を受け取り、2番目はOptionalを返すものを受け取ります。したがって、値をnullにすることはできないOptionalを返すことで、誰かに好意を示しているわけではありません。
それでも、Nullness Checkerが使用するアプローチは、NullPointerExceptionを実行時のバグからコンパイル時エラーに変換するため、Nullを処理するための最良の方法だと私は思います。