Sprievodca programom Java 8 Voliteľné

1. Prehľad

V tomto výučbe si ukážeme Voliteľné triedy, ktorá bola predstavená v Jave 8.

Účelom triedy je poskytnúť riešenie na úrovni typu pre zastupovanie voliteľných hodnôt namiesto nulový referencie.

Aby sme lepšie pochopili, prečo by nám malo záležať na Voliteľné triedy, pozrite si oficiálny článok spoločnosti Oracle.

2. Tvorenie Voliteľné Predmety

Existuje niekoľko spôsobov tvorby Voliteľné predmety.

Ak chcete vytvoriť prázdny údaj Voliteľné objekt, jednoducho musíme použiť jeho prázdne () statická metóda:

@ Test public void whenCreatesEmptyOptional_thenCorrect () {Voliteľné prázdne = Voliteľné.empty (); assertFalse (empty.isPresent ()); }

Všimnite si, že sme použili je prítomný() metóda na kontrolu, či sa vo vnútri súboru nachádza hodnota Voliteľné objekt. Hodnota je prítomná, iba ak sme vytvorili Voliteľné s ne-nulový hodnotu. Pozrime sa na je prítomný() v ďalšej časti.

Môžeme tiež vytvoriť Voliteľné objekt statickou metódou z ():

@Test public void givenNonNull_whenCreatesNonNullable_thenCorrect () {Názov reťazca = "baeldung"; Optional opt = Optional.of (name); assertTrue (opt.isPresent ()); }

Argument však prešiel na z () metóda nemôže byť nulový. V opačnom prípade dostaneme a NullPointerException:

@Test (očakáva sa = NullPointerException.class) public void givenNull_whenThrowsErrorOnCreate_thenCorrect () {Názov reťazca = null; Voliteľné.of (meno); }

Ale v prípade, že nejaké očakávame nulový hodnoty, môžeme použiť ofNullable () metóda:

@Test public void givenNonNull_whenCreatesNullable_thenCorrect () {Názov reťazca = "baeldung"; Voliteľné opt = Optional.ofNullable (meno); assertTrue (opt.isPresent ()); }

Týmto krokom, ak odovzdáme a nulový odkaz, nevyvolá výnimku, ale vráti prázdnu hodnotu Voliteľné objekt:

@ Test public void givenNull_whenCreatesNullable_thenCorrect () {Názov reťazca = null; Voliteľné opt = Optional.ofNullable (meno); assertFalse (opt.isPresent ()); }

3. Kontrola prítomnosti hodnoty: je prítomný() a je prázdny()

Keď máme Voliteľné objekt vrátený z metódy alebo vytvorený nami, môžeme skontrolovať, či je v ňom hodnota alebo nie pomocou je prítomný() metóda:

@Test public void givenOptional_whenIsPresentWorks_thenCorrect () {Optional opt = Optional.of ("Baeldung"); assertTrue (opt.isPresent ()); opt = Optional.ofNullable (null); assertFalse (opt.isPresent ()); }

Táto metóda sa vráti pravda ak zabalená hodnota nie je nulový.

Rovnako od Javy 11 môžeme robiť opak s je prázdny metóda:

@Test public void givenAnEmptyOptional_thenIsEmptyBehavesAsExected () {Optional opt = Optional.of ("Baeldung"); assertFalse (opt.isEmpty ()); opt = Optional.ofNullable (null); assertTrue (opt.isEmpty ()); }

4. Podmienené konanie s ifPresent ()

The ifPresent () metóda umožňuje spustiť nejaký kód na zabalenej hodnote, ak sa zistí, že nie jenulový. Predtým Voliteľné, urobili by sme:

if (name! = null) {System.out.println (name.length ()); }

Tento kód kontroluje, či je premenná názvu nulový alebo nie skôr, ako na ňom vykonáte nejaký kód. Tento prístup je zdĺhavý a nie je to jediný problém - je tiež náchylný na chyby.

Čo vlastne zaručuje, že po vytlačení tejto premennej ju znova a znova nepoužijeme zabudnúť vykonať nulovú kontrolu?

Môže to mať za následok a NullPointerException za behu, ak si do tohto kódu nájde hodnotu null. Ak program zlyhá z dôvodu problémov so vstupom, je to často dôsledok nesprávnych postupov pri programovaní.

Voliteľné núti nás zaoberať sa hodnotami s možnou hodnotou null výslovne ako spôsobom presadzovania osvedčených programovacích postupov.

Pozrime sa teraz na to, ako je možné vyššie uvedený kód refaktorovať v prostredí Java 8.

V typickom štýle funkčného programovania môžeme vykonať akciu na objekte, ktorý je v skutočnosti prítomný:

@Test public void givenOptional_whenIfPresentWorks_thenCorrect () {voliteľné opt = Optional.of ("baeldung"); opt.ifPresent (name -> System.out.println (name.length ())); }

Vo vyššie uvedenom príklade používame iba dva riadky kódu na nahradenie piatich, ktoré fungovali v prvom príklade: jeden riadok na zabalenie objektu do Voliteľné objekt a ďalší vykonať implicitnú validáciu, ako aj vykonať kód.

5. Predvolená hodnota s alebo iný()

The alebo iný() metóda sa používa na získanie hodnoty zabalenej vo vnútri Voliteľné inštancia. Trvá jeden parameter, ktorý slúži ako predvolená hodnota. The alebo iný() metóda vráti zabalenú hodnotu, ak je k dispozícii, a jej argument inak:

@Test public void whenOrElseWorks_thenCorrect () {String nullName = null; Názov reťazca = Optional.ofNullable (nullName) .orElse ("john"); assertEquals ("john", meno); }

6. Predvolená hodnota s orElseGet ()

The orElseGet () metóda je podobná ako alebo iný(). Namiesto toho, aby sa hodnota vrátila, ak Voliteľné hodnota nie je k dispozícii, vyžaduje sa funkčné rozhranie dodávateľa, ktoré sa vyvolá a vráti hodnotu vyvolania:

@Test public void whenOrElseGetWorks_thenCorrect () {String nullName = null; Názov reťazca = Optional.ofNullable (nullName) .orElseGet (() -> "john"); assertEquals ("john", meno); }

7. Rozdiel medzi alebo iný a orElseGet ()

Mnohým programátorom, ktorí sú v službe nováčikovia Voliteľné alebo Java 8, rozdiel medzi alebo iný() a orElseGet () nie je to jasné. Tieto dve metódy v skutočnosti budia dojem, že sa navzájom funkčne prekrývajú.

Existuje však jemný, ale veľmi dôležitý rozdiel medzi týmito dvoma, ktorý môže drasticky ovplyvniť výkonnosť nášho kódu, ak nie je dobre pochopený.

Vytvorme metódu s názvom getMyDefault () v testovacej triede, ktorá neberie žiadne argumenty a vráti predvolenú hodnotu:

public String getMyDefault () {System.out.println ("Získavam predvolenú hodnotu"); návrat "Predvolená hodnota"; }

Pozrime sa na dva testy a na pozorovanie ich vedľajších účinkov, aby sme zistili, kde sú alebo iný() a orElseGet () prekrývajú a v čom sa líšia:

@Test public void whenOrElseGetAndOrElseOverlap_thenCorrect () {text reťazca = null; Reťazec defaultText = Voliteľné.ofNullable (text) .orElseGet (this :: getMyDefault); assertEquals ("Predvolená hodnota", defaultText); defaultText = Voliteľné.ofNullable (text) .orElse (getMyDefault ()); assertEquals ("Predvolená hodnota", defaultText); }

Vo vyššie uvedenom príklade zalomíme nulový text dovnútra znaku Voliteľné objekt a pokúsiť sa získať zabalenú hodnotu pomocou každého z dvoch prístupov.

Vedľajším účinkom je:

Prebieha načítanie predvolenej hodnoty ... Prebieha načítanie predvolenej hodnoty ...

The getMyDefault () metóda sa volá v každom prípade. Stáva sa to tak ak zalomená hodnota nie je k dispozícii, potom obidve alebo iný() a orElseGet () fungujú úplne rovnako.

Teraz spustíme ďalší test, kde je hodnota k dispozícii a v ideálnom prípade by sa predvolená hodnota nemala ani vytvoriť:

@Test public void whenOrElseGetAndOrElseDiffer_thenCorrect () {String text = "Text present"; System.out.println ("Používanie orElseGet:"); Reťazec defaultText = Voliteľné.ofNullable (text) .orElseGet (this :: getMyDefault); assertEquals ("Text je prítomný", defaultText); System.out.println ("Používanie orElse:"); defaultText = Voliteľné.ofNullable (text) .orElse (getMyDefault ()); assertEquals ("Text je prítomný", defaultText); }

V uvedenom príklade už nezabalujeme a nulový hodnota a zvyšok kódu zostáva rovnaký.

Teraz sa pozrime na vedľajší efekt spustenia tohto kódu:

Using orElseGet: Using orElse: Getting default value ...

Všimnite si, že pri použití orElseGet () na získanie zabalenej hodnoty, getMyDefault () metóda nie je ani vyvolaná, pretože obsiahnutá hodnota je prítomná.

Avšak pri použití alebo iný(), či je zabalená hodnota prítomná alebo nie, vytvorí sa predvolený objekt. Takže v tomto prípade sme práve vytvorili jeden nadbytočný objekt, ktorý sa nikdy nepoužíva.

V tomto jednoduchom príklade neexistujú žiadne významné náklady na vytvorenie predvoleného objektu, pretože JVM s nimi vie zaobchádzať. Keď však metóda ako napr getMyDefault () musí uskutočniť volanie webovej služby alebo dokonca vyhľadať databázu, náklady sú veľmi zrejmé.

8. Výnimky s aleboElseThrow ()

The aleboElseThrow () metóda vyplýva z alebo iný() a orElseGet () a pridáva nový prístup k zaobchádzaniu s neprítomnou hodnotou.

Namiesto vrátenia predvolenej hodnoty, keď zabalená hodnota nie je k dispozícii, vyvolá výnimku:

@Test (očakáva sa = IllegalArgumentException.class) public void whenOrElseThrowWorks_thenCorrect () {String nullName = null; Názov reťazca = Optional.ofNullable (nullName) .orElseThrow (IllegalArgumentException :: new); }

Odkazy na metódy v prostredí Java 8 sa tu hodia na odovzdanie v konštruktore výnimiek.

Java 10 predstavila zjednodušenú verziu servera no-arg aleboElseThrow () metóda. V prípade prázdna Voliteľné hodí to NoSuchElelementException:

@Test (očakáva sa = NoSuchElementException.class) public void whenNoArgOrElseThrowWorks_thenCorrect () {String nullName = null; Názov reťazca = Optional.ofNullable (nullName) .orElseThrow (); }

9. Vrátenie hodnoty pomocou dostať ()

Konečným prístupom k získaniu zabalenej hodnoty je dostať () metóda:

@Test public void givenOptional_whenGetsValue_thenCorrect () {voliteľné opt = Optional.of ("baeldung"); Názov reťazca = opt.get (); assertEquals ("baeldung", meno); }

Na rozdiel od predchádzajúcich troch prístupov však dostať () môže vrátiť hodnotu, iba ak zabalený objekt nie je nulový; v opačnom prípade vrhá výnimku bez takýchto prvkov:

@Test (očakáva sa = NoSuchElementException.class) public void givenOptionalWithNull_whenGetThrowsException_thenCorrect () {Optional opt = Optional.ofNullable (null); Názov reťazca = opt.get (); }

Toto je hlavná chyba dostať () metóda. V ideálnom prípade Voliteľné by nám malo pomôcť vyhnúť sa takýmto nepredvídaným výnimkám. Preto tento prístup funguje v rozpore s cieľmi Voliteľné a pravdepodobne bude v budúcom vydaní zastaraná.

Preto je vhodné použiť ďalšie varianty, ktoré nám umožňujú pripraviť sa na a vyslovene zvládnuť nulový prípade.

10. Podmienený návrat s filter ()

Môžeme spustiť vložený test na našej zabalenej hodnote s filter metóda. Berie predikát ako argument a vráti znak Voliteľné objekt. Ak zalomená hodnota prejde testovaním predikátom, potom Voliteľné sa vracia tak, ako je.

Ak sa však predikát vráti nepravdivé, potom vráti prázdny Voliteľné:

@ Test public void whenOptionalFilterWorks_thenCorrect () {Celý rok = 2016; Optional yearOptional = Optional.of (year); boolean is2016 = yearOptional.filter (y -> y == 2016) .isPresent (); assertTrue (is2016); boolean is2017 = yearOptional.filter (y -> y == 2017) .isPresent (); assertFalse (is2017); }

The filter metóda sa bežne používa týmto spôsobom na odmietnutie zabalených hodnôt na základe preddefinovaného pravidla. Mohli by sme to použiť na odmietnutie nesprávneho formátu e-mailu alebo hesla, ktoré nie je dosť silné.

Pozrime sa na ďalší zmysluplný príklad. Povedzme, že si chceme kúpiť modem a záleží nám iba na jeho cene.

Z určitého webu dostávame push oznámenia o cenách modemu a tieto ukladáme do objektov:

modem verejnej triedy {private Double price; verejný modem (dvojnásobná cena) {this.price = cena; } // štandardní zakladatelia a zakladatelia}

Tieto objekty potom napájame na nejaký kód, ktorého jediným účelom je skontrolovať, či je cena modemu v rámci nášho rozsahu rozpočtu.

Poďme sa teraz pozrieť na kód bez Voliteľné:

public boolean priceIsInRange1 (modemový modem) {boolean isInRange = false; if (modem! = null && modem.getPrice ()! = null && (modem.getPrice ()> = 10 && modem.getPrice () <= 15)) {isInRange = true; } návrat isInRange; }

Venujte pozornosť tomu, koľko kódu musíme napísať, aby sme to dosiahli, najmä v ak stav. Jedinou časťou ak podmienkou, ktorá je pre aplikáciu kritická, je posledná kontrola cenového rozpätia; zvyšné kontroly sú obranné:

@Test public void whenFiltersWithoutOptional_thenCorrect () {assertTrue (priceIsInRange1 (new Modem (10.0))); assertFalse (priceIsInRange1 (nový modem (9.9))); assertFalse (priceIsInRange1 (nový modem (null))); assertFalse (priceIsInRange1 (nový modem (15.5))); assertFalse (priceIsInRange1 (null)); }

Okrem toho je možné zabudnúť na kontroly nuly počas dlhého dňa bez toho, aby ste dostali nejaké chyby pri kompilácii.

Teraz sa pozrime na variant s Voliteľný # filter:

public boolean priceIsInRange2 (Modem modem2) {return Optional.ofNullable (modem2) .map (Modem :: getPrice) .filter (p -> p> = 10) .filter (p -> p <= 15) .isPresent (); }

The mapa call sa jednoducho používa na transformáciu hodnoty na inú hodnotu. Pamätajte, že táto operácia nezmení pôvodnú hodnotu.

V našom prípade získavame cenový objekt od spoločnosti Model trieda. Pozrime sa na mapa () podrobne v nasledujúcej časti.

Najskôr, ak a nulový objekt je odovzdaný tejto metóde, neočakávame žiadny problém.

Po druhé, jediná logika, ktorú napíšeme do jej tela, je presne to, čo popisuje názov metódy - kontrola cenového rozpätia. Voliteľné stará sa o zvyšok:

@ Test public void whenFiltersWithOptional_thenCorrect () {assertTrue (priceIsInRange2 (new Modem (10.0))); assertFalse (priceIsInRange2 (nový modem (9.9))); assertFalse (priceIsInRange2 (nový modem (null))); assertFalse (priceIsInRange2 (nový modem (15.5))); assertFalse (priceIsInRange2 (null)); }

Predchádzajúci prístup sľubuje preverenie cenového rozpätia, ale musí urobiť viac ako to, aby sa ubránil proti svojej inherentnej krehkosti. Preto môžeme použiť filter metóda nahradenia nepotrebných ak výroky a odmietnuť nechcené hodnoty.

11. Transformácia hodnoty pomocou mapa ()

V predchádzajúcej časti sme sa pozreli na to, ako odmietnuť alebo prijať hodnotu na základe filtra.

Môžeme použiť podobnú syntax na transformáciu Voliteľné hodnota s mapa () metóda:

@Test public void givenOptional_whenMapWorks_thenCorrect () {List companyNames = Arrays.asList ("paypal", "oracle", "", "microsoft", "", "apple"); Voliteľné listOptional = Optional.of (companyNames); int size = listOptional .map (List :: size) .orElse (0); assertEquals (6, veľkosť); }

V tomto príklade zabalíme zoznam reťazcov dovnútra znaku Voliteľné objekt a použiť jeho mapa metóda na vykonanie akcie v obsiahnutom zozname. Akciou, ktorú vykonávame, je načítanie veľkosti zoznamu.

The mapa metóda vráti výsledok výpočtu zabaleného dovnútra Voliteľné. Potom musíme na vrátenú položku zavolať vhodnú metódu Voliteľné získať jeho hodnotu.

Všimnite si, že filter metóda jednoducho vykoná kontrolu hodnoty a vráti a boolovský. The mapa metóda však vezme existujúcu hodnotu, vykoná výpočet pomocou tejto hodnoty a vráti výsledok výpočtu zabalený do Voliteľné objekt:

@Test public void givenOptional_whenMapWorks_thenCorrect2 () {Názov reťazca = "baeldung"; Voliteľný nameOptional = Voliteľný.of (meno); int len ​​= nameOptional .map (String :: length) .orElse (0); assertEquals (8, len); }

Môžeme reťaziť mapa a filter spoločne urobiť niečo silnejšie.

Predpokladajme, že chceme skontrolovať správnosť hesla zadaného používateľom. Heslo môžeme vyčistiť pomocou a mapa transformáciu a skontrolujte jej správnosť pomocou a filter:

@Test public void givenOptional_whenMapWorksWithFilter_thenCorrect () {reťazec heslo = "heslo"; Optional passOpt = Optional.of (heslo); boolean correctPassword = passOpt.filter (pass -> pass.equals ("heslo")). isPresent (); assertFalse (correctPassword); correctPassword = passOpt .map (String :: trim) .filter (pass -> pass.equals ("heslo")) .isPresent (); assertTrue (correctPassword); }

Ako vidíme, bez predchádzajúceho vyčistenia vstupu bude odfiltrovaný - používatelia však môžu považovať za samozrejmé, že vstupný a koncový priestor tvoria vstup. Takže transformujeme špinavé heslo na čisté s znakom mapa pred odfiltrovaním nesprávnych.

12. Transformácia hodnoty pomocou flatMap ()

Rovnako ako mapa () metóda, máme tiež flatMap () metóda ako alternatíva pre transformáciu hodnôt. Rozdiel je v tom mapa transformuje hodnoty iba vtedy, keď sú rozbalené, zatiaľ čo flatMap vezme zabalenú hodnotu a pred transformáciou ju rozbalí.

Predtým sme vytvorili jednoduché String a Celé číslo predmety na zabalenie do Voliteľné inštancia. Tieto objekty však často dostaneme od prístupového objektu komplexného objektu.

Aby sme získali jasnejší obraz o rozdiele, pozrime sa na a Osoba objekt, ktorý berie údaje o osobe, ako je meno, vek a heslo:

public class Osoba {private String name; súkromný int vek; súkromné ​​reťazcové heslo; public Optional getName () {return Optional.ofNullable (name); } public Optional getAge () {return Optional.ofNullable (age); } public Voliteľné getPassword () {návrat Optional.ofNullable (heslo); } // normálni konštruktori a nastavovatelia}

Normálne by sme vytvorili taký objekt a zabalili by sme ho do Voliteľné objekt, ako sme to urobili s reťazcom.

Prípadne nám to môžete vrátiť iným volaním metódy:

Osoba osoba = nová osoba ("john", 26); Optional personOptional = Optional.of (person);

Všimnite si teraz, že keď zabalíme a Osoba objekt, bude obsahovať vnorené Voliteľné prípady:

@Test public void givenOptional_whenFlatMapWorks_thenCorrect2 () {Osoba osoba = nová Osoba ("john", 26); Optional personOptional = Optional.of (person); Voliteľné nameOptionalWrapper = personOptional.map (Person :: getName); Voliteľný nameOptional = nameOptionalWrapper.orElseThrow (IllegalArgumentException :: new); Reťazec name1 = nameOptional.orElse (""); assertEquals ("john", meno1); Názov reťazca = personOptional .flatMap (Person :: getName) .orElse (""); assertEquals ("john", meno); }

Tu sa pokúšame načítať atribút názvu súboru Osoba namietať proti vykonaniu tvrdenia.

Všimnite si, ako to dosiahneme mapa () v treťom výroku a potom si všimnite, ako to robíme s flatMap () metóda potom.

The Osoba :: getName odkaz na metódu je podobný Reťazec :: orezanie hovor, ktorý sme mali v predchádzajúcej časti na vyčistenie hesla.

Rozdiel je iba v tom getName () vracia Voliteľné skôr ako reťazec ako trim () prevádzka. To spolu so skutočnosťou, že a mapa transformácia zalomí výsledok do Voliteľné objekt, vedie k vnorenému Voliteľné.

Počas používania mapa () Metóda preto musíme pridať ďalšie volanie na získanie hodnoty pred použitím transformovanej hodnoty. Týmto spôsobom Voliteľné obal bude odstránený. Táto operácia sa pri použití vykonáva implicitne flatMap.

13. Reťazenie Voliteľnés v prostredí Java 8

Niekedy možno budeme musieť dostať prvé neprázdne Voliteľné objekt z množstva Voliteľnés. V takýchto prípadoch by bolo veľmi vhodné použiť metódu ako orElseOptional (). Táto operácia bohužiaľ nie je priamo podporovaná v prostredí Java 8.

Najprv si predstavíme niekoľko metód, ktoré v tejto časti použijeme:

private Optional getEmpty () {return Optional.empty (); } private Voliteľné getHello () {return Optional.of ("ahoj"); } private Optional getBye () {return Optional.of ("bye"); } private Optional createOptional (String input) {if (input == null || "" .equals (input) || "empty" .equals (input)) {return Optional.empty (); } návrat Optional.of (vstup); }

S cieľom reťaziť niekoľko Voliteľné objekty a získame prvý neprázdny v Jave 8, môžeme použiť Prúd API:

@Test public void givenThreeOptionals_whenChaining_thenFirstNonEmptyIsReturned () {voliteľné nájdené = Stream.of (getEmpty (), getHello (), getBye ()) .filter (voliteľné :: isPresent) .map (voliteľné :: získanie) .findFirst (); assertEquals (getHello (), nájdené); }

Nevýhodou tohto prístupu je, že všetci dostať metódy sa vykonávajú vždy, bez ohľadu na to, kde sú neprázdne Voliteľné sa objaví v Prúd.

Ak chceme lenivo vyhodnotiť odovzdané metódy Stream.of (), musíme použiť odkaz na metódu a Dodávateľ rozhranie:

@Test public void givenThreeOptionals_whenChaining_thenFirstNonEmptyIsReturnedAndRestNotEvaluated () {Voliteľné nájdené = Stream.<>> of (this :: getEmpty, this :: getHello, this :: getBye) .map (Supplier :: get) .filter (Optional :: isPresent) .map (Optional :: get) .findFirst (); assertEquals (getHello (), nájdené); }

V prípade, že potrebujeme použiť metódy, ktoré berú argumenty, musíme sa uchýliť k výrazom lambda:

@Test public void givenTwoOptionalsReturnedByOneArgMethod_whenChaining_thenFirstNonEmptyIsReturned () {Nájdené voliteľné = Stream.<>> of (() -> createOptional ("empty"), () -> createOptional ("hello")) .map (Supplier :: get) .filter (Optional :: isPresent) .map (Optional :: get). findFirst (); assertEquals (createOptional ("ahoj"), nájdené); }

Často budeme chcieť vrátiť predvolenú hodnotu v prípade, že sú všetky zreťazené Voliteľnésú prázdne. Môžeme tak urobiť iba pridaním hovoru na alebo iný() alebo orElseGet ():

@Test public void givenTwoEmptyOptionals_whenChaining_thenDefaultIsReturned () {String found = Stream.<>> of (() -> createOptional ("empty"), () -> createOptional ("empty")) .map (Supplier :: get) .filter (Optional :: isPresent) .map (Optional :: get). findFirst () .orElseGet (() -> "predvolené"); assertEquals ("predvolené", nájdené); }

14. JDK 9 Voliteľné API

Vydanie Java 9 pridalo do systému ešte viac nových metód Voliteľné API:

  • alebo () metóda poskytovania dodávateľa, ktorý vytvára alternatívu Voliteľné
  • ifPresentOrElse () metóda, ktorá umožňuje vykonať akciu, ak Voliteľné je prítomný alebo iná akcia, ak nie
  • Prúd() metóda premeny Voliteľné do a Prúd

Tu je celý článok na ďalšie čítanie.

15. Zneužitie Voliteľnés

Na záver sa pozrime na lákavý, aj keď nebezpečný spôsob použitia Voliteľnés: absolvovanie an Voliteľné parameter na metódu.

Predstavte si, že máme zoznam Osoba a chceme metódu vyhľadávania v tomto zozname ľudí s daným menom. Tiež by sme chceli, aby táto metóda priraďovala položky aspoň s určitým vekom, ak je uvedený.

Keďže je tento parameter voliteľný, prichádzame s touto metódou:

verejné statické vyhľadávanie v zozname (zoznam ľudí, meno reťazca, voliteľný vek) {// Nulová kontrola osôb a návrat mena people.stream () .filter (p -> p.getName (). equals (name)) .filter (p -> p.getAge (). get ()> = age.orElse (0)) .collect (Collectors.toList ()); }

Potom našu metódu uvoľníme a ďalší vývojár sa ju pokúsi použiť:

someObject.search (people, "Peter", null);

Teraz vývojár vykoná svoj kód a dostane znak NullPointerException.Sme tu a musíme skontrolovať svoju voliteľnú hodnotu, čo ruší náš pôvodný účel, keď sa chceme vyhnúť takejto situácii.

Tu je niekoľko možností, ktoré sme mohli urobiť, aby sme to lepšie zvládli:

verejné statické vyhľadávanie v zozname (zoznam ľudí, meno reťazca, celé číslo veku) {// Null skontroluje prítomnosť ľudí a meno konečné celé číslo ageFilter = vek! = null? vek: 0; návrat people.stream () .filter (p -> p.getName (). equals (name)) .filter (p -> p.getAge (). get ()> = ageFilter) .collect (Collectors.toList () ); }

Tam je parameter stále voliteľný, ale zvládneme ho iba v jednej kontrole.

Iná možnosť by bola vytvoriť dve preťažené metódy:

verejné statické vyhľadávanie v zozname (zoznam ľudí, meno reťazca) {návrat do vyhľadávania (ľudia, meno, 0); } verejné statické vyhľadávanie v zozname (zoznam ľudí, meno reťazca, vek) {return doSearch (ľudia, meno, vek); } private static List doSearch (List people, String name, int age) {// Nulová kontrola osôb a návrat mena people.stream () .filter (p -> p.getName (). equals (name)) .filter ( p -> p.getAge (). get (). intValue ()> = vek) .collect (Collectors.toList ()); }

Takto ponúkame prehľadné API s dvoma metódami, ktoré umožňujú rôzne veci (aj keď zdieľajú implementáciu).

Existujú teda riešenia, ktorým sa treba vyhnúť Voliteľnés ako parametre metódy. Zámer Javy pri uvoľnení Voliteľné bolo použiť ho ako návratový typ, čo naznačuje, že metóda môže vrátiť prázdnu hodnotu. Ako v skutočnosti, prax používania Voliteľné ako parameter metódy je niektorými inšpektormi kódu dokonca odradený.

16. Voliteľné a Serializácia

Ako bolo uvedené vyššie, Voliteľné je určený na použitie ako návratový typ. Pokúšať sa ho použiť ako typ poľa sa neodporúča.

Navyše, použitím Voliteľné v serializovateľnej triede bude mať za následok a NotSerializableException. Náš článok Java Voliteľné as Return Type ďalej rieši problémy so serializáciou.

A v časti Používanie Voliteľné S Jacksonom vysvetľujeme, čo sa kedy stane Voliteľné polia sú serializované spolu s niekoľkými riešeniami na dosiahnutie požadovaných výsledkov.

17. Záver

V tomto článku sme sa venovali väčšine dôležitých funkcií Java 8 Voliteľné trieda.

Krátko sme preskúmali niekoľko dôvodov, prečo by sme sa rozhodli použiť Voliteľné namiesto explicitnej kontroly nuly a validácie vstupu.

Tiež sme sa naučili, ako získať hodnotu súboru Voliteľnéalebo predvolený, ak je prázdny, s dostať (), alebo iný() a orElseGet () metódy (a videl dôležitý rozdiel medzi poslednými dvoma).

Potom sme videli, ako transformovať alebo filtrovať naše Voliteľnés s mapa (), flatMap () a filter (). Diskutovali sme o tom, čo plynulo APIVoliteľné ponúka, pretože nám umožňuje ľahko spojiť rôzne metódy.

Nakoniec sme videli, prečo používať Voliteľnés ako parameter metódy je zlý nápad a ako sa mu vyhnúť.

Zdrojový kód pre všetky príklady v článku je k dispozícii na GitHub.


$config[zx-auto] not found$config[zx-overlay] not found