Vodič za Javu 8 Izborno

1. Pregled

U ovom uputstvu ćemo pokazati Neobvezno razred koji je uveden u Javi 8.

Svrha klase je pružiti rješenje na razini tipa za predstavljanje neobaveznih vrijednosti umjesto null reference.

Da bismo dublje razumjeli zašto bismo trebali brinuti o Neobvezno razreda, pogledajte službeni članak Oraclea.

2. Stvaranje Neobvezno Predmeti

Postoji nekoliko načina stvaranja Neobvezno predmeta.

Da biste stvorili prazno Neobvezno objekt, jednostavno moramo koristiti njegov prazan() statička metoda:

@Test public void whenCreatesEmptyOptional_thenCorrect () {Neobvezno prazno = Izborno.empty (); assertFalse (empty.isPresent ()); }

Imajte na umu da smo koristili je prisutan() metoda za provjeru postoji li vrijednost unutar datoteke Neobvezno objekt. Vrijednost je prisutna samo ako smo stvorili Neobvezno s ne-null vrijednost. Pogledat ćemo je prisutan() metoda u sljedećem odjeljku.

Također možemo stvoriti Neobvezno objekt statičkom metodom od():

@Test javna praznina givenNonNull_whenCreatesNonNullable_thenCorrect () {String name = "baeldung"; Neobvezno opt = Neobvezno.of (ime); assertTrue (opt.isPresent ()); }

Međutim, argument je proslijeđen na od() metoda ne može biti null. Inače ćemo dobiti NullPointerException:

@Test (očekuje se = NullPointerException.class) javna praznina givenNull_whenThrowsErrorOnCreate_thenCorrect () {Naziv niza = null; Neobvezno.of (ime); }

Ali u slučaju da neke očekujemo null vrijednosti, možemo koristiti odNullable () metoda:

@Test javna praznina givenNonNull_whenCreatesNullable_thenCorrect () {String name = "baeldung"; Neobvezno opt = Neobvezno.ofNullable (ime); assertTrue (opt.isPresent ()); }

Čineći to, ako prođemo u null referenca, ne izbacuje iznimku, već vraća prazno Neobvezno objekt:

@Test javna praznina givenNull_whenCreatesNullable_thenCorrect () {Naziv niza = null; Neobvezno opt = Neobvezno.ofNullable (ime); assertFalse (opt.isPresent ()); }

3. Provjera prisutnosti vrijednosti: je prisutan() i prazno je()

Kad imamo Neobvezno objekt vraćen iz metode ili stvoren od nas, možemo provjeriti postoji li vrijednost u njemu ili ne pomoću je prisutan() metoda:

@Test javna praznina givenOptional_whenIsPresentWorks_thenCorrect () {Izborno opt = Neobvezno.of ("Baeldung"); assertTrue (opt.isPresent ()); opt = Neobvezno.ofNullable (null); assertFalse (opt.isPresent ()); }

Ova metoda se vraća pravi ako zamotana vrijednost nije null.

Također, od Jave 11, možemo učiniti suprotno s prazno je metoda:

@Test javna praznina givenAnEmptyOptional_thenIsEmptyBehavesAsExpected () {Neobvezno opt = Neobvezno.of ("Baeldung"); assertFalse (opt.isEmpty ()); opt = Neobvezno.ofNullable (null); assertTrue (opt.isEmpty ()); }

4. Uvjetno djelovanje sa ifPresent ()

The ifPresent () metoda omogućuje nam pokretanje nekog koda na umotanoj vrijednosti ako se utvrdi da nijenull. Prije Neobvezno, napravili bismo:

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

Ovaj kod provjerava je li varijabla imena null ili ne prije nego što krenemo izvršavati neki kod na njemu. Ovaj je pristup dugotrajan i to nije jedini problem - također je sklon pogreškama.

Doista, ono što jamči da je nakon ispisa te varijable nećemo koristiti ponovno i tada zaboraviti izvršiti null provjeru?

To može rezultirati a NullPointerException u vrijeme izvođenja ako se null vrijednost nađe u tom kodu. Kada program zakaže zbog problema s unosom, to je često rezultat loše prakse programiranja.

Neobvezno tjera nas da se izričito bavimo null vrijednostima kao načinom provođenja dobrih programskih praksi.

Pogledajmo sada kako bi se gornji kod mogao refaktorirati u Javi 8.

U tipičnom funkcionalnom stilu programiranja možemo izvršiti izvođenje radnje na objektu koji je zapravo prisutan:

@Test javna praznina givenOptional_whenIfPresentWorks_thenCorrect () {Neobvezno opt = Neobvezno.of ("baeldung"); opt.ifPresent (name -> System.out.println (name.length ())); }

U gornjem primjeru koristimo samo dva retka koda kako bismo zamijenili pet koji su radili u prvom primjeru: jedan redak za umotavanje objekta u Neobvezno objekt i sljedeći koji će izvršiti implicitnu provjeru valjanosti, kao i izvršiti kôd.

5. Zadana vrijednost sa ili drugo()

The ili drugo() metoda koristi se za dohvaćanje vrijednosti umotane u Neobvezno primjer. Potreban je jedan parametar, koji djeluje kao zadana vrijednost. The ili drugo() metoda vraća zamotanu vrijednost ako je prisutna, a njezin argument u suprotnom:

@Test public void whenOrElseWorks_thenCorrect () {String nullName = null; Ime niza = Izborno.ofNullable (nullName) .orElse ("john"); assertEquals ("john", ime); }

6. Zadana vrijednost sa iliElseGet ()

The orElseGet () metoda je slična ili drugo(). Međutim, umjesto da uzme vrijednost koju treba vratiti ako Neobvezno vrijednost nije prisutna, potrebno je funkcionalno sučelje dobavljača, koje se poziva i vraća vrijednost poziva:

@Test public void whenOrElseGetWorks_thenCorrect () {String nullName = null; Ime niza = Izborno.ofNullable (nullName) .orElseGet (() -> "john"); assertEquals ("john", ime); }

7. Razlika između ili drugo i orElseGet ()

Mnogim programerima koji su novi u Neobvezno ili Java 8, razlika između ili drugo() i orElseGet () nije jasno. Zapravo, ove dvije metode daju dojam da se međusobno funkcionalno preklapaju.

Međutim, postoji suptilna, ali vrlo važna razlika između njih dvije koja može drastično utjecati na izvedbu našeg koda ako se ne razumije dobro.

Stvorimo metodu tzv getMyDefault () u test klasi, koja ne uzima argumente i vraća zadanu vrijednost:

javni String getMyDefault () {System.out.println ("Dobivanje zadane vrijednosti"); return "Zadana vrijednost"; }

Pogledajmo dva testa i promatrajmo njihove nuspojave kako bismo utvrdili gdje ili drugo() i orElseGet () preklapaju se i gdje se razlikuju:

@Test public void whenOrElseGetAndOrElseOverlap_thenCorrect () {Tekst niza = null; Niz defaultText = Izborno.ofNullable (tekst) .orElseGet (ovo :: getMyDefault); assertEquals ("Zadana vrijednost", defaultText); defaultText = Neobvezno.ofNullable (tekst) .orElse (getMyDefault ()); assertEquals ("Zadana vrijednost", defaultText); }

U gornjem primjeru nula tekst umotavamo u Neobvezno objekt i pokušajte dobiti zamotanu vrijednost koristeći svaki od dva pristupa.

Nuspojava je:

Dobivanje zadane vrijednosti ... Dobivanje zadane vrijednosti ...

The getMyDefault () metoda se poziva u svakom slučaju. Tako se dogodi da kada umotana vrijednost nije prisutna, tada oboje ili drugo() i orElseGet () raditi potpuno na isti način.

Ajmo sada pokrenuti još jedan test gdje je vrijednost prisutna, a idealno bi bilo da se zadana vrijednost ne bi trebala niti stvarati:

@Test public void whenOrElseGetAndOrElseDiffer_thenCorrect () {String text = "Tekst prisutan"; System.out.println ("Korištenje orElseGet:"); Niz defaultText = Izborno.ofNullable (tekst) .orElseGet (ovo :: getMyDefault); assertEquals ("Tekst prisutan", defaultText); System.out.println ("Korištenje orElse:"); defaultText = Neobvezno.ofNullable (tekst) .orElse (getMyDefault ()); assertEquals ("Tekst prisutan", defaultText); }

U gornjem primjeru više ne omotavamo a null vrijednost, a ostatak koda ostaje isti.

Pogledajmo sada nuspojavu izvođenja ovog koda:

Korištenje orElseGet: Korištenje orElse: Dobivanje zadane vrijednosti ...

Primijetite da prilikom upotrebe orElseGet () za dohvaćanje umotane vrijednosti, getMyDefault () metoda se čak ni ne poziva jer je sadržana vrijednost prisutna.

Međutim, prilikom korištenja ili drugo(), bez obzira je li omotana vrijednost prisutna ili ne, stvara se zadani objekt. U ovom smo slučaju upravo stvorili jedan suvišni objekt koji se nikada ne koristi.

U ovom jednostavnom primjeru nema značajnih troškova za stvaranje zadanog objekta, jer JVM zna kako se nositi s takvim. Međutim, kada metoda poput getMyDefault () mora uputiti poziv web usluzi ili čak upiti bazu podataka, trošak postaje vrlo očit.

8. Iznimke sa iliElseThrow ()

The iliElseThrow () metoda slijedi iz ili drugo() i orElseGet () i dodaje novi pristup za rukovanje odsutnom vrijednošću.

Umjesto vraćanja zadane vrijednosti kada omotana vrijednost nije prisutna, ona izuzima iznimku:

@Test (očekuje se = IllegalArgumentException.class) javna praznina kadaOrElseThrowWorks_thenCorrect () {Niz nullName = null; Ime niza = Izborno.ofNullable (nullName) .orElseThrow (IllegalArgumentException :: novo); }

Referencije metoda u Javi 8 dobro nam dolaze ovdje za prosljeđivanje u konstruktoru iznimke.

Java 10 predstavila je pojednostavljenu verziju no-arg iliElseThrow () metoda. U slučaju prazne Neobvezno baca a NoSuchElelementException:

@Test (očekuje se = NoSuchElementException.class) javna praznina kadaNoArgOrElseThrowWorks_thenCorrect () {Niz nullName = null; Ime niza = Izborno.ofNullable (nullName) .orElseThrow (); }

9. Povratna vrijednost sa dobiti()

Konačni pristup za dohvaćanje zamotane vrijednosti je dobiti() metoda:

@Test javna praznina givenOptional_whenGetsValue_thenCorrect () {Neobvezno opt = Neobvezno.of ("baeldung"); Naziv niza = opt.get (); assertEquals ("baeldung", ime); }

Međutim, za razliku od prethodna tri pristupa, dobiti() može vratiti vrijednost samo ako omotani objekt nije null; u suprotnom, baca iznimku bez takvih elemenata:

@Test (očekuje se = NoSuchElementException.class) javna praznina givenOptionalWithNull_whenGetThrowsException_thenCorrect () {Neobvezno opt = Opcionalno.ofNullable (null); Naziv niza = opt.get (); }

Ovo je glavna mana dobiti() metoda. Idealno, Neobvezno bi nam trebao pomoći da izbjegnemo takve nepredviđene iznimke. Stoga se ovaj pristup protivi ciljevima Neobvezno i vjerojatno će biti zastario u budućem izdanju.

Stoga je poželjno koristiti ostale inačice koje nam omogućuju da se pripremimo i eksplicitno obradimo null slučaj.

10. Uvjetni povratak sa filtar()

Možemo pokrenuti inline test na našoj umotanoj vrijednosti pomoću filtar metoda. Uzima predikat kao argument i vraća znak Neobvezno objekt. Ako zamotana vrijednost prođe testiranje u predikatu, tada Neobvezno vraća se kakav jest.

Međutim, ako se predikat vrati lažno, tada će vratiti prazno Neobvezno:

@Test public void whenOptionalFilterWorks_thenCorrect () {Integer year = 2016; Izborno yearOptional = Izborno.of (godine); boolean is2016 = yearOptional.filter (y -> y == 2016) .isPresent (); assertTrue (is2016); boolean is2017 = yearOptional.filter (y -> y == 2017) .isPresent (); assertFalse (is2017); }

The filtar metoda se obično koristi na ovaj način za odbacivanje zamotanih vrijednosti na temelju unaprijed definiranog pravila. Mogli bismo ga koristiti za odbijanje pogrešnog formata e-pošte ili lozinke koja nije dovoljno jaka.

Pogledajmo još jedan suvisli primjer. Recimo da želimo kupiti modem i brinemo samo o njegovoj cijeni.

S određene web lokacije primamo push obavijesti o cijenama modema i pohranjujemo ih u predmete:

modem javne klase {privatno Dvostruka cijena; javni modem (dvostruka cijena) {this.price = cijena; } // standardni getteri i postavljači}

Zatim te objekte hranimo nekim kodom čija je jedina svrha provjeriti nalazi li se cijena modema u našem proračunu.

Pogledajmo sada kod bez Neobvezno:

javna logička cijenaIsInRange1 (modem modem) {boolean isInRange = false; if (modem! = null && modem.getPrice ()! = null && (modem.getPrice ()> = 10 && modem.getPrice () <= 15)) {isInRange = true; } return isInRange; }

Obratite pažnju na to koliko koda moramo napisati da bismo to postigli, posebno u ako stanje. Jedini dio ako uvjet koji je presudan za aplikaciju je posljednja provjera raspona cijena; ostatak provjera je obrambeni:

@Test javna void whenFiltersWithoutOptional_thenCorrect () {assertTrue (priceIsInRange1 (novi modem (10.0))); assertFalse (priceIsInRange1 (novi modem (9.9))); assertFalse (priceIsInRange1 (novi modem (null))); assertFalse (priceIsInRange1 (novi modem (15.5))); assertFalse (priceIsInRange1 (null)); }

Osim toga, moguće je zaboraviti na null provjere tijekom dugog dana, a da pritom ne dobijete nikakve pogreške tijekom kompajliranja.

Pogledajmo sada varijantu s Izborni # filter:

javna logička cijenaIsInRange2 (modem modem2) {return Izborno.ofNullable (modem2) .map (Modem :: getPrice) .filter (p -> p> = 10) .filter (p -> p <= 15) .isPresent (); }

The karta poziv se jednostavno koristi za pretvaranje vrijednosti u neku drugu vrijednost. Imajte na umu da ovaj postupak ne mijenja izvornu vrijednost.

U našem slučaju dobivamo objekt cijene od Model razred. Pogledat ćemo karta() metoda detaljno u sljedećem odjeljku.

Prije svega, ako a null objekt prosljeđuje se ovoj metodi, ne očekujemo nikakav problem.

Drugo, jedina logika koju zapisujemo unutar njezina tijela je upravo ono što naziv metode opisuje - provjera raspona cijena. Neobvezno brine o ostatku:

@Test javna void whenFiltersWithOptional_thenCorrect () {assertTrue (priceIsInRange2 (novi modem (10.0))); assertFalse (priceIsInRange2 (novi modem (9.9))); assertFalse (priceIsInRange2 (novi modem (null))); assertFalse (priceIsInRange2 (novi modem (15.5))); assertFalse (priceIsInRange2 (null)); }

Prethodni pristup obećava provjeru raspona cijena, ali mora učiniti i više od toga da bi se obranio od svojstvene krhkosti. Stoga možemo koristiti filtar metoda za zamjenu nepotrebnih ako izjave i odbacuju neželjene vrijednosti.

11. Transformiranje vrijednosti pomoću karta()

U prethodnom smo odjeljku pogledali kako odbiti ili prihvatiti vrijednost na temelju filtra.

Sličnu sintaksu možemo koristiti za transformiranje datoteke Neobvezno vrijednost s karta() metoda:

@Test javna praznina givenOptional_whenMapWorks_thenCorrect () {Popis kompanijaNames = Arrays.asList ("paypal", "oracle", "", "microsoft", "", "apple"); Neobvezno listOptional = Izborno.of (companyNames); int size = listO optional .map (List :: size) .orElse (0); assertEquals (6, veličina); }

U ovom primjeru umotavamo popis nizova unutar Neobvezno objekt i koristiti svoj karta metoda za izvođenje radnje na sadržanom popisu. Akcija koju izvodimo je dohvaćanje veličine popisa.

The karta metoda vraća rezultat izračuna umotan unutra Neobvezno. Zatim moramo vratiti odgovarajuću metodu na vraćenom Neobvezno kako bi dohvatio njegovu vrijednost.

Primijetite da filtar metoda jednostavno vrši provjeru vrijednosti i vraća a boolean. The karta metoda međutim uzima postojeću vrijednost, izvodi proračun pomoću te vrijednosti i vraća rezultat izračuna zamotan u Neobvezno objekt:

@Test javna praznina givenOptional_whenMapWorks_thenCorrect2 () {String name = "baeldung"; Neobvezno nameO optional = Neobvezno.of (ime); int len ​​= nameO optional .map (String :: length) .orElse (0); assertEquals (8, len); }

Možemo lančati karta i filtar zajedno učiniti nešto moćnije.

Pretpostavimo da želimo provjeriti ispravnost unosa lozinke od strane korisnika. Lozinku možemo očistiti pomoću a karta transformaciju i provjerite njezinu ispravnost pomoću a filtar:

@Test javna praznina givenOptional_whenMapWorksWithFilter_thenCorrect () {String password = "password"; Neobvezno passOpt = Neobvezno.of (lozinka); logička ispravna lozinka = passOpt.filter (pass -> pass.equals ("lozinka")). isPresent (); assertFalse (točnaPassword); ispravnaPassword = passOpt .map (String :: trim) .filter (pass -> pass.equals ("lozinka")) .isPresent (); assertTrue (ispravnaPassword); }

Kao što vidimo, bez prethodnog čišćenja ulaza on će se filtrirati - no korisnici mogu uzimati zdravo za gotovo da vodeći i prateći razmaci čine ulaz. Dakle, prljavu lozinku pretvaramo u čistu pomoću a karta prije filtriranja netočnih.

12. Transformiranje vrijednosti pomoću flatMap ()

Baš kao i karta() metodu, imamo i flatMap () metoda kao alternativa za transformiranje vrijednosti. Razlika je u tome karta transformira vrijednosti samo kad su razmotane dok flatMap uzima zamotanu vrijednost i odmotava je prije transformiranja.

Prije smo stvorili jednostavno Niz i Cijeli broj predmeti za umotavanje u Neobvezno primjer. Međutim, često ćemo te objekte dobivati ​​od pristupnika složenom objektu.

Da bismo dobili jasniju sliku razlike, pogledajmo a Osoba objekt koji uzima podatke o osobi kao što su ime, dob i lozinka:

javni razred Osoba {ime privatnog niza; privatno int doba; privatna lozinka za niz; javno Izborno getName () {return Izborno.ofNullable (ime); } javni Izborni getAge () {return Izborni.ofNullable (dob); } javni Izborni getPassword () {povratak Izborni.ofNullable (lozinka); } // normalni konstruktori i postavljači}

Obično bismo stvorili takav objekt i zamotali ga u Neobvezno objekt kao što smo to učinili sa Stringom.

Alternativno, može nam se vratiti putem drugog poziva metode:

Osoba osoba = nova osoba ("john", 26); Neobvezna osobaO optional = Neobvezna.of (osoba);

Primijetite sada da kada omotamo a Osoba objekt, sadržavat će ugniježđeno Neobvezno primjerci:

@Test javna praznina givenOptional_whenFlatMapWorks_thenCorrect2 () {Osoba osoba = nova osoba ("john", 26); Neobvezna osobaObavezna = Neobvezna.od (osobe); Neobvezno nameOptionalWrapper = personOptional.map (Person :: getName); Neobvezno nameOptional = nameOptionalWrapper.orElseThrow (IllegalArgumentException :: new); String name1 = nameOptional.orElse (""); assertEquals ("john", ime1); Ime niza = personOptional .flatMap (Person :: getName) .orElse (""); assertEquals ("john", ime); }

Ovdje pokušavamo dobiti atribut name datoteke Osoba objekt za izvođenje tvrdnje.

Primijetite kako to postižemo s karta() u trećoj izjavi, a zatim primijetite kako to činimo s flatMap () metoda poslije.

The Osoba :: getName Referenca metode slična je String :: trim poziv koji smo imali u prethodnom odjeljku za čišćenje lozinke.

Jedina je razlika u tome getName () vraća an Neobvezno a ne niz kao što je to učinio obrezati () operacija. To, zajedno s činjenicom da a karta transformacija obavija rezultat u Neobvezno objekt, vodi do ugniježđenog Neobvezno.

Dok se koristi karta() zato moramo dodati dodatni poziv za dohvaćanje vrijednosti prije korištenja transformirane vrijednosti. Ovim putem, Neobvezno omot će biti uklonjen. Ova se operacija izvodi implicitno kada se koristi flatMap.

13. Ulančavanje Neobveznos u Javi 8

Ponekad ćemo možda morati dobiti prvi koji nije prazan Neobvezno objekt iz niza Neobveznos. U takvim bi slučajevima bilo vrlo prikladno koristiti metodu poput iliElseOptional (). Nažalost, takva operacija nije izravno podržana u Javi 8.

Uvedimo prvo nekoliko metoda koje ćemo koristiti u ovom odjeljku:

private Neobvezno getEmpty () {return Opcionalno.empty (); } private Izborno getHello () {return Izborno.of ("hello"); } private Neobvezno getBye () {return Opcionalno.of ("bye"); } private Neobvezno createOptional (String input) {if (input == null || "" .equals (input) || "empty" .equals (input)) {return Neobvezno.empty (); } return Optional.of (input); }

Kako bi se lancirali nekoliko Neobvezno objekata i dobiti prvi neprazan u Java 8, možemo koristiti Stream API:

@Test javna praznina givenThreeOptionals_whenChaining_thenFirstNonEmptyIsReturned () {Neobvezno pronađeno = Stream.of (getEmpty (), getHello (), getBye ()) .filter (Neobvezno :: isPresent) .map (Neobavezno :: get) .findFirst () assertEquals (getHello (), pronađeno); }

Loša strana ovog pristupa je što su svi naši dobiti metode se uvijek izvršavaju, bez obzira gdje nije prazno Neobvezno pojavljuje se u Stream.

Ako želimo lijeno procijeniti metode predane Stream.of (), trebamo koristiti referencu metode i Dobavljač sučelje:

@Test javna praznina givenThreeOptionals_whenChaining_thenFirstNonEmptyIsReturnedAndRestNotEvaluated () {Neobvezno pronađeno = Stream.<>> od (this :: getEmpty, this :: getHello, this :: getBye) .map (Dobavljač :: get) .filter (Neobvezno :: isPresent) .map (Neobvezno :: get) .findFirst (); assertEquals (getHello (), pronađeno); }

U slučaju da trebamo koristiti metode koje uzimaju argumente, moramo posegnuti za lambda izrazima:

@Test javna praznina givenTwoOptionalsReturnedByOneArgMethod_whenChaining_thenFirstNonEmptyIsReturned () {Neobvezno pronađeno = Stream.<>> of (() -> createOptional ("empty"), () -> createOptional ("hello")) .map (Supplier :: get) .filter (Neobvezno :: isPresent) .map (Neobvezno :: get). findFirst (); assertEquals (createOptional ("zdravo"), pronađeno); }

Često ćemo htjeti vratiti zadanu vrijednost u slučaju da su svi ulančani Neobveznos su prazne. To možemo učiniti samo dodavanjem poziva na ili drugo() ili orElseGet ():

@Test javna praznina givenTwoEmptyOptionals_whenChaining_thenDefaultIsReturned () {String found = Stream.<>> od (() -> createOptional ("prazno"), () -> createOptional ("prazno")) .map (Dobavljač :: get) .filter (Neobvezno :: isPresent) .map (Neobavezno :: get). findFirst () .orElseGet (() -> "zadani"); assertEquals ("zadano", pronađeno); }

14. JDK 9 Neobvezno API

Izdanje Java 9 dodalo je još više novih metoda u Neobvezno API:

  • ili() metoda pružanja dobavljača koji stvara alternativu Neobvezno
  • ifPresentOrElse () metoda koja omogućuje izvršavanje radnje ako Neobvezno je prisutan ili druga radnja ako nije
  • stream () metoda za pretvorbu Neobvezno do a Stream

Evo cjelovitog članka za daljnje čitanje.

15. Zlouporaba Neobveznos

Napokon, pogledajmo primamljiv, koliko god opasan bio način upotrebe Neobveznos: polaganje an Neobvezno parametar metode.

Zamislite da imamo popis Osoba i želimo da metoda pretražuje taj popis osoba s određenim imenom. Također, željeli bismo da se ta metoda podudara s unosima barem određene dobi, ako je navedena.

Budući da ovaj parametar nije obvezan, dolazimo s ovom metodom:

javno statično pretraživanje popisa (Popis ljudi, ime niza, neobavezna dob) {// Null provjerava ljude i ime vraća people.stream () .filter (p -> p.getName (). jednako (ime)) .filter (p -> p.getAge (). get ()> = age.orElse (0)) .collect (Collectors.toList ()); }

Tada objavljujemo našu metodu, a drugi je programer pokušava koristiti:

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

Sada programer izvršava svoj kod i dobiva NullPointerException.Tu smo, moramo nulirati naš neobavezni parametar, što poništava našu početnu svrhu želeći izbjeći takvu situaciju.

Evo nekoliko mogućnosti koje smo mogli učiniti da bismo to bolje riješili:

javno statično pretraživanje popisa (Popis ljudi, ime niza, cijela dob) {// Null provjerava ljude i ime konačno Integer ageFilter = age! = null? dob: 0; vratiti ljude.stream () .filter (p -> p.getName (). jednako (ime)) .filter (p -> p.getAge (). get ()> = ageFilter) .collect (Collectors.toList () ); }

Tamo je parametar još uvijek neobavezan, ali obrađujemo ga u samo jednoj provjeri.

Druga mogućnost bila bi stvoriti dvije preopterećene metode:

javno statično pretraživanje popisa (Popis ljudi, ime niza) {return doSearch (ljudi, ime, 0); } javno statično pretraživanje popisa (Popis ljudi, ime niza, int age) {return doSearch (ljudi, ime, dob); } privatni statički popis doSearch (Popis ljudi, ime niza, int age) {// Null provjerava ljude i ime vraća people.stream () .filter (p -> p.getName (). jednako (ime)) .filter ( p -> p.getAge (). get (). intValue ()> = dob) .collect (Collectors.toList ()); }

Na taj način nudimo jasan API s dvije metode koje rade različite stvari (iako dijele implementaciju).

Dakle, postoje rješenja koja treba izbjegavati koristiti Neobveznos kao parametri metode. Namjera Jave prilikom izdavanja Neobvezno je koristiti kao povratni tip, što ukazuje na to da metoda može vratiti praznu vrijednost. Zapravo, praksa korištenja Neobvezno jer neki inspektori koda čak obeshrabruju parametar metode.

16. Neobvezno i serializacija

Kao što je gore spomenuto, Neobvezno je namijenjen upotrebi kao povratnom tipu. Ne preporučuje se pokušaj korištenja kao vrste polja.

Dodatno, koristeći Neobvezno u serializabilnoj klasi rezultirat će a NotSerializableException. Naš članak Java Neobvezno kao Return Type dalje rješava probleme sa serializacijom.

I, u Korištenje Neobvezno S Jacksonom objašnjavamo što se događa kad Neobvezno polja su serializirana, zajedno s nekoliko zaobilaznih rješenja kako bi se postigli željeni rezultati.

17. Zaključak

U ovom smo članku pokrili većinu važnih značajki Jave 8 Neobvezno razred.

Ukratko smo istražili neke razloge zašto bismo se odlučili koristiti Neobvezno umjesto eksplicitne provjere nule i provjere unosa.

Također smo naučili kako dobiti vrijednost Neobvezno, ili zadani ako je prazan, s dobiti(), ili drugo() i orElseGet () metode (i uvidio važnu razliku između posljednje dvije).

Tada smo vidjeli kako transformirati ili filtrirati svoje Neobveznos s map (), flatMap () i filtar(). Raspravljali smo o tome kako tečno APINeobvezno nudi, jer nam omogućuje lako ulančavanje različitih metoda.

Napokon smo vidjeli zašto koristiti Neobveznos kao parametri metode loša je ideja i kako to izbjeći.

Izvorni kod za sve primjere u članku dostupan je na GitHubu.