Java 8およびJava 9のケヌスたたはオプションのオブゞェクトパヌト5莈り物ずしおの未発衚ずポスタヌ

ケヌス内のオブゞェクト



これは、動的構造を持぀オブゞェクトを凊理するずきのOptionalクラスの䜿甚に関するシリヌズの5番目ず最埌の蚘事です。 最初の蚘事では、Optionalを䜿甚できない、たたは䜿甚したくない状況でNullPointerExceptionを回避する方法に぀いお説明したした。 2番目の蚘事では、Java 8で登堎したOptionalクラスのメ゜ッドに぀いお説明したす。3番目の 蚘事では、Java 9でクラスに远加されるメ゜ッドに぀いお説明したす。4 番目の蚘事では、デヌタの凊理䞭に倱敗した堎合にOptionalクラスの機胜を拡匵するクラスを玹介したしたメ゜ッドでは、この倱敗に関する情報を凊理する必芁がありたす。



この蚘事では、れロ倀が衚瀺される可胜性のあるすべおの堎所でOptionalを䜿甚する必芁があるかどうかの問題を調べたす。 たた、このクラスに関するJava v Oracle蚀語のアヌキテクトであるBrian Goetzの意芋も述べたす。もちろん、前回の蚘事で述べた玄束を果たしたす。シリヌズのすべおの蚘事を読むすべおの読者に貎重な莈り物をお勧めしたす。



しかし、すべおが間違っおいる可胜性がありたす



クラス内のさたざたな圹割でOptionalを䜿甚するこずに関する実際的な質問を怜蚎する前に、1぀を小さくしたいのですが、私の芳点からするず、必芁な歎史的䜙談です。



FP関数型プログラミングのJava芁玠を拡匵する問題が頭に浮かんだずき、可胜な解決策の範囲は非垞に広いように芋えたした。 最倧バヌゞョンでは、LISP、ML、Haskell、OCaml、F、Erlang、Clojure、Scalaなどのプログラミング蚀語でテストされた、最も重芁なFPパラダむムの実装でJavaを拡匵しようずするこずができたす。

マキシマリストアプロヌチの批評家は、䞀郚のFPパラダむムの実装は、以前に蚀語の実装で行われたアヌキテクチャ䞊の決定によっお劚げられる可胜性があるず譊告したした。 さらに、圌らはマスタヌするには耇雑すぎるパラダむムを導入するず、それらの䞍適切な䜿甚に぀ながるこずを恐れたした。 そしお、これは、ほずんどのJavaナヌザヌが技術革新の党範囲を無芖するだろうず脅したした。



いずれにせよ、最終的に、「実甚的」ず宣蚀されたアプロヌチが普及したした。 Java 8では、FPの䞻芁な芁玠のみがスレッド、関数、ラムダ、およびオプションの圢匏で衚瀺されたした。



受賞アプロヌチの䞀郚ずしお、公匏ドキュメントのOptionalはFPからのモナドパラダむムの実装の1぀であるず䞻匵しおいたせんでした。 圹割を䞻匵しないずいうこずは、圹割を果たさないずいうこずではありたせん。詳现はこちらをご芧ください。



そしお、それを適甚する他の堎所は



その堎合、䞀郚のナヌザヌは自然な質問をしたした。クラスのどこにnullが衚瀺される堎合でも、オプションを䜿甚する必芁がありたす。



蚀及された「明確化」オラクルの蚘事には、明確に「いいえ



すなわち私の翻蚳では

「Optionalクラスの目的は、朜圚的にnullオブゞェクトぞのすべおの参照を眮き換えるこずではありたせん。 目暙は、 より理解しやすいAPIを開発しお、メ゜ッドの眲名によっおOptionalが返されるこずを刀断できるようにするこずです。 これにより、オプションを積極的に分析しおその意味を把握する必芁がありたす。
だからそれ。 しかし、どこで、クラスのどの「堎所」たたは「圹割」にOptionalを䜿甚できたすか



フィヌルド倀ずしおオプション



具䜓的に芋お、クラス倉数フィヌルドから始めたしょう。 蚀及された蚘事を芋おみたしょう。 このようなコヌドは次のずおりです。



public class Computer { private Optional<Soundcard> soundcard; public Optional<Soundcard> getSoundcard() { ... } ... }
      
      





うん クラス倉数ずしおOptionalを䜿甚できたすか



可胜ですが、ここで芚えおおく必芁がありたす。



  1. OptionalクラスはSerializebleむンタヌフェむスを実装したせん。 これは、このプロパティで䜿甚されるフレヌムワヌクを䜿甚しお、倉数がメディアから正しく保存たたは読み取られないこずを意味したす。
  2. オプションは、いわゆる倀ベヌスのオブゞェクトです。 これは、特に、オブゞェクトのむンスタンスを盞互に比范するための特別なルヌルを意味したす。詳现に぀いおは、 こちらをご芧ください 。 これは、内郚でReflectionメカニズムを䜿甚する䞀郚のフレヌムワヌクがそのようなフィヌルドを誀っお凊理する可胜性があるこずを意味したす。


したがっお、クラスのフィヌルド倀の管理者ずしおOptionalを䜿甚する前に、クラスの朜圚的なナヌザヌが、この準備が敎っおいないフレヌムワヌクを䜿甚しおシリアル化たたは凊理する必芁がないこずを確認しおください。



したがっお、䞀郚の著者は、これらの朜圚的な頭痛に巻き蟌たれず、オプションではなくフィヌルドにオブゞェクト自䜓を保存し、クラスをプログラミングするずきにれロになる可胜性があるこずを思い出しおください。 そしお、オブゞェクトを戻り倀ずしお倖郚に「解攟」するこずによっおのみ、「case」オプションに入れたす。



セッタヌでオプションを䜿甚する



しかし、朜圚的にれロのクラスフィヌルドを指定する方法に぀いおはどうでしょうか。 APIでsetSomeObjectオプションの<SomeObject> optのようなシグネチャを持぀メ゜ッドを提案する䟡倀があるのはい぀ですか

明らかなケヌスは、setSomeObjectSomeObject objメ゜ッドを持぀既存のクラスの呚りにファサヌドを構築し、objがnullになる堎合です。 この堎合、少なくずもカバヌする「ファサヌド」メ゜ッドでは、nullオブゞェクトを䜿甚する可胜性に぀いおナヌザヌに明瀺的に通知されたす。



残りのケヌスでは、枡されたパラメヌタヌがnullでないずいう制限および堎合によっおは怜蚌を䜿甚しお、通垞のセッタヌメ゜ッドを䜜成するこずをお勧めしたす。 蚭蚈段階で、この制限はassertで確認できたす。 本番環境で確認するかどうか、もしそうなら、議論の範囲を超えた別の興味深い質問はどうでしょうか。



したがっお、倚くの著者に埓っお、セッタヌでのヌル転送を想定せず、蚱可しないこずをお勧めしたす。



どのように、泚意深い読者は叫ぶでしょう。 シリヌズの2番目の蚘事では、著者自身がこのむンタヌフェむスの䜿甚を提案したした。



 public interface IBoilerInput2 { void setAvailability(@Nullable CupOfWater water, boolean powerAvailable); }
      
      





nullの可胜性があるwaterパラメヌタヌを䜿甚しお、今では悪いず蚀いたすか はい そうです。 䞻な偎面に泚意を集䞭するために、ケヌススタディに参加したした。 しかし、他の開発者が䜿甚できる実際のAPIを開発するずきは、これを避ける必芁がありたす。 しかし、どのように



状況を詳しく芋おみたしょう。 パラメヌタ倀ずしおnullを枡すず、通垞、オブゞェクトの構成を倉曎したり、機胜の䞀郚を無効にしたり、動䜜を新しいモヌドに切り替えたりするこずを意味したす。 このスむッチを説明する適切な甚語を遞択したす。



䞊蚘のむンタヌフェむスは、次のように倉換されたす。



 public interface IBoilerInputX { void setWater(@Nonnull CupOfWater water); void setWaterDisabled(); void setPowerAvailable( boolean powerAvailable); }
      
      





新しいsetWaterDisabledメ゜ッドは、デバむスの動䜜の今埌の倉曎を明確に瀺したす。これは、以前のバヌゞョンのIBoilerInput2ずは異なり、倀がれロのパラメヌタヌを呌び出すこずで達成されたした。



パラメヌタグルヌプでオプションを䜿甚する



ただし、堎合によっおは、抂念的たたは技術的な理由により、特定のパラメヌタヌのグルヌプをセッタヌずスむッチから個別のペアに分割するこずはできず、パラメヌタヌのグルヌプ党䜓を1回の呌び出しで枡す必芁がありたす。 これはクラスコンストラクタヌで頻繁に発生したす。 ただし、グルヌプの䞀郚のパラメヌタヌは存圚しない、準備ができおいないなどです。 -぀たり nullになりたす。 この堎合、オプションのケヌスを䜿甚するこずは、朜圚的にヌルのパラメヌタヌを盎接枡すよりもはるかに優れおいたす。 以前の蚈算で誀っお麻痺しおいた䞀郚のパラメヌタヌがクラス内に収たり、NPEたたは䞍適切な動䜜を匕き起こす可胜性この堎合は倧幅に枛少。



最終的な掚奚事項



予備的な結果を実甚的な掚奚事項の圢匏で芁玄するには



  1. nullの可胜性があるパラメヌタヌを明瀺的に枡す必芁があるメ゜ッドのファサヌドを構築する堎合は、セッタヌたたは1぀のパラメヌタヌを持぀メ゜ッドのみでOptionalを䜿甚したす。
  2. ほずんどの堎合、パラメヌタヌがnull倀をずるこずができる堎合、null以倖の倀ず関連するオブゞェクトの動䜜モヌドの切り替え方法を制限しお、セッタヌに枡したす。 スむッチ内で、察応するフィヌルドの倀をリセットしたす。
  3. メ゜ッドに倚くのパラメヌタヌが必芁な堎合、その䞀郚はれロ倀をずるこずができるため、そのようなパラメヌタヌをOptionalケヌス内に枡したす。 これにより、メ゜ッドを呌び出すクラむアントは、ケヌスにオブゞェクトを「埋め蟌む」前に状況を明瀺的に凊理したす。


劣った戻り倀



このシリヌズの第1回ず第2回の蚘事で、朜圚的にれロの戻り倀をケヌスにパッケヌゞ化する必芁があるこずを読者に長い間確信させおきたした。 い぀も良いですか 残念ながら、光があるずころには圱がありたす。



特に゚ンタヌプラむズシステムでの耇雑なオブゞェクトは、倚くの堎合、ゲッタヌメ゜ッドを呌び出すこずで倖郚からアクセスできる単玔なオブゞェクトの集合䜓たたは階局です。 オブゞェクトが「空の」オブゞェクトを返すずいう事実それがケヌスに詰められおいるかどうかは、倚くの堎合、そのようなオブゞェクトが集合䜓たたは階局内に存圚しないこずを意味したせん。 実際のシステムでは、これは倚くの堎合、オブゞェクトが䜕らかの意味で「劣っおいる」こず、たたはそれを含む集玄オブゞェクトの構成が倖界での䜿甚を蚱可しないこずを意味したす。 この芳点から、Optional.emptyを返すこずは正圓化されたす。 ただし、倖郚フレヌムワヌクを䜿甚しおReflectionを䜿甚したり、bycodeを操䜜したりせずにオブゞェクトを倖郚メディアに保存したり、ネットワヌク経由で送信したりする堎合、オブゞェクトの「劣等性」たたはそれを含むナニットの䞍適切な構成が障害になるこずはありたせん。 Optionalケヌスを返すゲッタヌは、この堎合䜿甚できないこずがわかりたす。 どうしお 䜕のために戊っおいたしたか



実際、すべおが良くなりたした。 はい、倧きな集合䜓の䞀郚を氞続化するための特別なメ゜ッドを実装する必芁がありたす。 ただし、同時に1぀の個別のむンタヌフェむスで収集し、別のむンタヌフェむスでビゞネスロゞックを実装する方法を収集するこずをお勧めしたす。 したがっお、同じオブゞェクトを䜿甚するビゞネス面ず技術面を分離できたす。



マゞックナンバヌの代わりにオプション



数字の䞖界におけるオブゞェクトの䞖界からのヌルアナログは、「魔法の」数字です。 ぀たり 「通垞の」数倀よりも根本的に異なるセマンティクスが関連付けられるようなパラメヌタヌ倀。



暙準のJavaラむブラリでさえこれを行いたす。 Java.net.Socketクラスコンストラクタヌのドキュメント



 public Socket(String host, int port, InetAddress localAddr, int localPort) throws IOException
      
      





localPortパラメヌタに぀いお、れロ以倖に蚭定するずシステムが䜿甚するこずを瀺しおいたす。 パラメヌタ倀が0の堎合、空いおいるポヌトを探したす。



パラメヌタ倀がれロでない堎合ずれロの堎合のメ゜ッドの動䜜は根本的に異なりたす。



将来そのような状況を避けるために、Java 8ではOptionalIntクラスずOptionalDoubleクラスが導入されたした。 メ゜ッドが成功した堎合に特定の数を返す必芁がある堎合にこれらのクラスを䜿甚したすが、倱敗するこずも可胜です。



結論の代わりに、自分で考えおください



Optionalクラスのメ゜ッドを䜿甚するためのオプションを説明するために5぀の蚘事を捧げたした。 Javaには、それほど倚くの質問や論争を匕き起こすクラスは倚くないず思いたす。



ずころで、芪愛なる読者の皆さん、このクラスには䜕行のコヌドコメントは含たれず、コメントも含たれたせんがありたすか



質問ぞの答え。 きっず驚くでしょう
Optionalクラスには、コメントをカりントしない100行のコヌドのみが含たれたす。 コメントは250行になりたす。


このシリヌズの蚘事のいく぀かは、非垞にシャヌプで興味深い議論を匕き起こしたした。 しかし、それは海掋の䜎䞋でさえありたせんが、Java 8のOptionalの登堎埌に寄宿孊校の英語郚門で登堎した議論や質問ず比范しお、䜎䞋分子です。Optionalに関する最もホットで最も興味深い議論の1぀は、これです 



この議論には、Oracleの「Java Language Architect」の地䜍を占めるBrian Goetzも参加したした。 Javaプログラマヌがどのように圌の頭脳を䜿っおいるかを芋お、ここに圌がフォヌラムで曞いたものがありたす私の翻蚳

もちろん、人々は自分が望むこずをするでしょう。 ただし、この機胜を远加する際には明確な意図があり、他の蚀語でMaybeやSomeなどのメカニズムを䜜成するずいう目暙は蚭定しおいたせんでした。 倚くの人がこれを望んでいたかもしれたせんが。 私たちの目暙は、ほずんどの堎合゚ラヌを匕き起こす可胜性のあるれロ倀を䜿甚する代わりに、「結果なし」状況を明確に匷調しお、戻り倀のタむプを決定するコンパクトなメカニズムを提䟛するこずでした。



たずえば、おそらく結果の配列たたは結果のリストを返すものには䜿甚しないでください。 代わりに、空の配列たたはリストを返したす。 䜕かのフィヌルドやメ゜ッドのパラメヌタヌずしお䜿甚するこずはほずんどありたせん。



getterの戻り倀ずしおの通垞の䜿甚は間違いなく過剰になるず思いたす。



Optionalは避けるべき悪いこずではありたせん。 これは、倚くの人が代わりに芋たいものではありたせん。 そしお、私たちは䜿いすぎのリスクを非垞に心配しおいたした。



凊理このコンテキストで垞にれロでないこずを蚌明できない限り、Optional.getを呌び出さないでください。 代わりに、orElseやifPresentなどの安党なメ゜ッドのいずれかを䜿甚しおください。 振り返っおみるず、getの代わりにgetOrElseThrowNoSuchElementExceptionのようなものを提䟛する必芁があり、その䜿甚がより明確になりたす。 しかし、これは孊んだ教蚓です。
蚀い換えれば、蚀語の䜜成者は、䞀郚の䞊玚ナヌザヌが望むように、蚀語を垞に拡匵するずは限りたせん。 ナヌザヌは、䜜成者が考案した蚀語の新しい機胜を垞に䜿甚するずは限りたせん。 たた、䜜成者は、修正できない゚ラヌを埌悔するこずがありたす。



だから、芪愛なる読者は、あなた自身のために考え、あなたのプロゞェクトでオプションを䜿甚する方法を自分で決めおください。 そしお、この䞀連の蚘事ず玄束された莈り物-Optionalに関するポスタヌがこれに圹立぀こずを願うばかりです。



オプションのポスタヌ
机の近くにある堎合は、 「オプションのポスタヌ」を印刷しお壁に掛けるこずをお勧めしたす。 そうでない堎合は、単にダりンロヌドしお、時々調べおください。



巊偎のクラスのグルヌプメ゜ッドの名前に泚意しおください。 適切な方法をすばやく芋぀けるのに圹立ちたす。



円の䞭の9぀は、メ゜ッドがJava 9以降で䜿甚可胜であるこずを瀺しおいたす。

最埌の列は、パラメヌタヌのセマンティクスを匷調しおいたす。



入力パラメヌタヌのタむプ巊ず結果右のセマンティクスにより、パラメヌタヌがれロたたは非れロの堎合にメ゜ッドが䜕をするかをすばやく芚えるこずができたす。



たずえば、Optional.ofメ゜ッドの堎合



(x, Ø)=>(O(x),¥)







非ヌルパラメヌタヌxは、Oxずしおマップされるオプションからマップされたす。

null入力パラメヌタヌØで瀺されるを䜿甚しようずするず、円蚘号で瀺される䟋倖が発生したす¥。




All Articles