Guide til Java 8 Valgfri

1. Oversigt

I denne vejledning skal vi vise Valgfri klasse, der blev introduceret i Java 8.

Formålet med klassen er at give en typeløsning til at repræsentere valgfri værdier i stedet for nul referencer.

For at få en dybere forståelse af, hvorfor vi skal bekymre os om Valgfri klasse, se på den officielle Oracle-artikel.

2. Oprettelse Valgfri Objekter

Der er flere måder at skabe på Valgfri genstande.

At oprette en tom Valgfri objekt, er vi simpelthen nødt til at bruge dens tom() statisk metode:

@Test offentlig ugyldig nårCreatesEmptyOptional_thenCorrect () {Valgfri tom = Optional.empty (); assertFalse (tom.isPresent ()); }

Bemærk, at vi brugte er til stede() metode til at kontrollere, om der er en værdi inde i Valgfri objekt. En værdi er kun til stede, hvis vi har oprettet Valgfri med en ikke-nul værdi. Vi ser på er til stede() metode i det næste afsnit.

Vi kan også oprette en Valgfri objekt med den statiske metode af():

@Test offentlig ugyldighed givenNonNull_whenCreatesNonNullable_thenCorrect () {String name = "baeldung"; Valgfri opt = Optional.of (navn); assertTrue (opt.isPresent ()); }

Imidlertid blev argumentet videregivet til af() metode kan ikke være nul. Ellers får vi en NullPointerException:

@Test (forventet = NullPointerException.class) offentlig ugyldighed givenNull_whenThrowsErrorOnCreate_thenCorrect () {String name = null; Valgfri. Af (navn); }

Men hvis vi forventer noget nul værdier, kan vi bruge ofNullable () metode:

@ Test offentligt ugyldigt givenNonNull_whenCreatesNullable_thenCorrect () {String name = "baeldung"; Valgfri opt = Optional.ofNullable (navn); assertTrue (opt.isPresent ()); }

Ved at gøre dette, hvis vi passerer i en nul reference, det kaster ikke en undtagelse, men returnerer snarere en tom Valgfri objekt:

@Test offentlig ugyldighed givenNull_whenCreatesNullable_thenCorrect () {String name = null; Valgfri opt = Optional.ofNullable (navn); assertFalse (opt.isPresent ()); }

3. Kontrol af værditilstedeværelse: er til stede() og er tom()

Når vi har en Valgfri objekt returneret fra en metode eller oprettet af os, kan vi kontrollere, om der er en værdi i det eller ej med er til stede() metode:

@Test offentligt ugyldigt givetOptional_whenIsPresentWorks_thenCorrect () {Valgfri opt = Optional.of ("Baeldung"); assertTrue (opt.isPresent ()); opt = Optional.ofNullable (null); assertFalse (opt.isPresent ()); }

Denne metode vender tilbage rigtigt hvis den indpakkede værdi ikke er nul.

Også fra Java 11 kan vi gøre det modsatte med er tom metode:

@ Test offentligt ugyldigt givenAnEmptyOptional_thenIsEmptyBehavesAsExpected () {Valgfri opt = Optional.of ("Baeldung"); assertFalse (opt.isEmpty ()); opt = Optional.ofNullable (null); assertTrue (opt.isEmpty ()); }

4. Betinget handling med ifPresent ()

Det ifPresent () metode gør det muligt for os at køre en kode på den indpakkede værdi, hvis den viser sig at være ikke-nul. Før Valgfri, vi ville gøre:

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

Denne kode kontrollerer, om navnet variabel er nul eller ikke før du fortsætter med at udføre en kode på den. Denne tilgang er lang, og det er ikke det eneste problem - det er også udsat for fejl.

Faktisk, hvad der garanterer, at efter udskrivning af denne variabel, bruger vi den ikke igen og da glemmer at udføre nulcheck?

Dette kan resultere i en NullPointerException ved kørsel, hvis en nulværdi finder vej ind i den kode. Når et program mislykkes på grund af inputproblemer, er det ofte et resultat af dårlig programmeringspraksis.

Valgfri får os til at håndtere ugyldige værdier eksplicit som en måde at håndhæve god programmeringspraksis på.

Lad os nu se på, hvordan ovenstående kode kunne omformuleres i Java 8.

I typisk funktionel programmeringsstil kan vi udføre en handling på et objekt, der faktisk er til stede:

@Test offentligt ugyldigt givetOptional_whenIfPresentWorks_thenCorrect () {Valgfri opt = Optional.of ("baeldung"); opt.ifPresent (navn -> System.out.println (navn.længde ())); }

I ovenstående eksempel bruger vi kun to linier kode til at erstatte de fem, der fungerede i det første eksempel: en linje til at pakke objektet ind i en Valgfri objekt og det næste til at udføre implicit validering samt udføre koden.

5. Standardværdi med ellers()

Det ellers() metode bruges til at hente den værdi, der er pakket ind i en Valgfri eksempel. Det tager en parameter, der fungerer som en standardværdi. Det ellers() metoden returnerer den indpakkede værdi, hvis den er til stede, og dens argument ellers:

@Test offentlig ugyldig nårOrElseWorks_thenCorrect () {String nullName = null; String name = Optional.ofNullable (nullName) .orElse ("john"); assertEquals ("john", navn); }

6. Standardværdi med orElseGet ()

Det orElseGet () metoden ligner ellers(). Imidlertid i stedet for at tage en værdi at returnere, hvis Valgfri værdi er ikke til stede, det tager en leverandørfunktionel grænseflade, der påberåbes og returnerer værdien af ​​påkaldelsen:

@Test offentlig ugyldig nårOrElseGetWorks_thenCorrect () {String nullName = null; String name = Optional.ofNullable (nullName) .orElseGet (() -> "john"); assertEquals ("john", navn); }

7. Forskellen mellem ellers og orElseGet ()

For mange programmerere, der er nye til Valgfri eller Java 8, forskellen mellem ellers() og orElseGet () er ikke klart. Faktisk giver disse to metoder indtryk af, at de overlapper hinanden i funktionalitet.

Der er dog en subtil, men meget vigtig forskel mellem de to, der kan påvirke udførelsen af ​​vores kode drastisk, hvis den ikke forstås godt.

Lad os oprette en metode kaldet getMyDefault () i testklassen, der ikke tager nogen argumenter og returnerer en standardværdi:

offentlig streng getMyDefault () {System.out.println ("Få standardværdi"); returner "Standardværdi"; }

Lad os se to tests og observere deres bivirkninger for at fastslå begge hvor ellers() og orElseGet () overlapning, og hvor de adskiller sig:

@Test offentlig ugyldig nårOrElseGetAndOrElseOverlap_thenCorrect () {String text = null; Streng defaultText = Optional.ofNullable (tekst) .orElseGet (dette :: getMyDefault); assertEquals ("Standardværdi", defaultText); defaultText = Optional.ofNullable (text) .orElse (getMyDefault ()); assertEquals ("Standardværdi", defaultText); }

I eksemplet ovenfor pakker vi en nultekst ind i en Valgfri modstand og forsøg på at få den indpakkede værdi ved hjælp af hver af de to tilgange.

Bivirkningen er:

Henter standardværdi ... Henter standardværdi ...

Det getMyDefault () metode kaldes i hvert tilfælde. Det sker således, at når den indpakkede værdi ikke er til stede, så begge ellers() og orElseGet () arbejde nøjagtigt på samme måde.

Lad os nu køre en anden test, hvor værdien er til stede, og ideelt set bør standardværdien ikke engang oprettes:

@Test offentlig ugyldig nårOrElseGetAndOrElseDiffer_thenCorrect () {String text = "Tekst til stede"; System.out.println ("Brug af orElseGet:"); Streng defaultText = Optional.ofNullable (tekst) .orElseGet (dette :: getMyDefault); assertEquals ("Text present", defaultText); System.out.println ("Brug af orElse:"); defaultText = Optional.ofNullable (text) .orElse (getMyDefault ()); assertEquals ("Text present", defaultText); }

I eksemplet ovenfor pakker vi ikke længere en nul værdi, og resten af ​​koden forbliver den samme.

Lad os nu se på bivirkningen ved at køre denne kode:

Brug af orElseGet: Brug af orElse: Henter standardværdi ...

Bemærk, at når du bruger orElseGet () for at hente den indpakkede værdi, getMyDefault () metode påberåbes ikke engang, da den indeholdte værdi er til stede.

Dog ved brug ellers(), uanset om den indpakkede værdi er til stede eller ej, oprettes standardobjektet. Så i dette tilfælde har vi netop oprettet et overflødigt objekt, der aldrig bruges.

I dette enkle eksempel er der ingen væsentlige omkostninger ved at oprette et standardobjekt, da JVM ved, hvordan man skal håndtere sådan. Når en metode som f.eks getMyDefault () skal foretage et webtjenesteopkald eller endda spørge til en database, bliver omkostningerne meget åbenlyse.

8. Undtagelser med orElseThrow ()

Det orElseThrow () metoden følger af ellers() og orElseGet () og tilføjer en ny tilgang til håndtering af en fraværende værdi.

I stedet for at returnere en standardværdi, når den indpakkede værdi ikke er til stede, kaster den en undtagelse:

@Test (forventet = IllegalArgumentException.class) offentlig ugyldig nårOrElseThrowWorks_thenCorrect () {String nullName = null; String name = Optional.ofNullable (nullName) .orElseThrow (IllegalArgumentException :: new); }

Metodehenvisninger i Java 8 er nyttige her for at videregive undtagelseskonstruktøren.

Java 10 introducerede en forenklet no-arg version af orElseThrow () metode. I tilfælde af en tom Valgfri det kaster en NoSuchElelementException:

@Test (forventet = NoSuchElementException.class) offentlig ugyldig nårNoArgOrElseThrowWorks_thenCorrect () {String nullName = null; String name = Optional.ofNullable (nullName) .orElseThrow (); }

9. Returneringsværdi med få()

Den sidste tilgang til at hente den indpakkede værdi er få() metode:

@Test offentlig ugyldighed givetOptional_whenGetsValue_thenCorrect () {Valgfri opt = Optional.of ("baeldung"); String name = opt.get (); assertEquals ("baeldung", navn); }

I modsætning til de tre foregående tilgange, få() kan kun returnere en værdi, hvis det indpakkede objekt ikke er nul; ellers kaster det en ikke sådan elementundtagelse:

@Test (forventet = NoSuchElementException.class) offentlig ugyldighed givenOptionalWithNull_whenGetThrowsException_thenCorrect () {Valgfri opt = Optional.ofNullable (null); String name = opt.get (); }

Dette er den største fejl i få() metode. Ideelt set Valgfri skulle hjælpe os med at undgå sådanne uforudsete undtagelser. Derfor fungerer denne tilgang mod målene for Valgfri og vil sandsynligvis blive udfaset i en fremtidig udgivelse.

Så det tilrådes at bruge de andre varianter, der gør det muligt for os at forberede os på og eksplicit håndtere nul sag.

10. Betinget retur med filter()

Vi kan køre en inline test på vores indpakket værdi med filter metode. Det tager et predikat som argument og returnerer et Valgfri objekt. Hvis den indpakkede værdi består test ved prædikatet, så Valgfri returneres som den er.

Men hvis prædikatet vender tilbage falsk, så returnerer den en tom Valgfri:

@Test offentlig ugyldigt nårOptionalFilterWorks_thenCorrect () {Heltal = 2016; Valgfrit yearOptional = Optional.of (år); boolsk is2016 = yearOptional.filter (y -> y == 2016) .isPresent (); assertTrue (is2016); boolsk is2017 = yearOptional.filter (y -> y == 2017) .isPresent (); assertFalse (is2017); }

Det filter metode bruges normalt på denne måde til at afvise indpakkede værdier baseret på en foruddefineret regel. Vi kunne bruge det til at afvise et forkert e-mail-format eller en adgangskode, der ikke er stærk nok.

Lad os se på et andet meningsfuldt eksempel. Sig, at vi vil købe et modem, og vi er kun interesserede i prisen.

Vi modtager push-meddelelser om modempriser fra et bestemt sted og gemmer disse i objekter:

offentlig klasse Modem {privat Dobbeltpris; offentligt modem (dobbelt pris) {this.price = pris; } // standard getters og setters}

Derefter føder vi disse objekter til en kode, hvis eneste formål er at kontrollere, om modemprisen er inden for vores budget.

Lad os nu se på koden uden Valgfri:

public boolean priceIsInRange1 (Modem modem) {boolean isInRange = false; hvis (modem! = null && modem.getPrice ()! = null && (modem.getPrice ()> = 10 && modem.getPrice () <= 15)) {isInRange = true; } returnering erInRange; }

Vær opmærksom på, hvor meget kode vi skal skrive for at opnå dette, især i hvis tilstand. Den eneste del af hvis betingelse, der er kritisk for applikationen, er den sidste prisklasse-kontrol; resten af ​​kontrollen er defensiv:

@Test offentlig ugyldig nårFiltersWithoutOptional_thenCorrect () {assertTrue (priceIsInRange1 (nyt modem (10.0))); assertFalse (priceIsInRange1 (nyt modem (9.9))); assertFalse (priceIsInRange1 (nyt modem (null))); assertFalse (priceIsInRange1 (nyt modem (15.5))); assertFalse (priceIsInRange1 (null)); }

Bortset fra det er det muligt at glemme nulchecks over en lang dag uden at få nogen kompileringstidsfejl.

Lad os nu se på en variant med Valgfrit # filter:

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

Det kort opkald bruges simpelthen til at omdanne en værdi til en anden værdi. Husk, at denne handling ikke ændrer den oprindelige værdi.

I vores tilfælde får vi et prisobjekt fra Model klasse. Vi vil se på kort() metode i detaljer i det næste afsnit.

Først og fremmest, hvis en nul objekt sendes til denne metode, vi forventer ikke noget problem.

For det andet er den eneste logik, vi skriver inde i dens krop, nøjagtigt hvad metodenavnet beskriver - prisklasse-kontrol. Valgfri tager sig af resten:

@Test offentlig ugyldig nårFiltersWithOptional_thenCorrect () {assertTrue (priceIsInRange2 (nyt modem (10.0))); assertFalse (priceIsInRange2 (nyt modem (9.9))); assertFalse (priceIsInRange2 (nyt modem (null))); assertFalse (priceIsInRange2 (nyt modem (15.5))); assertFalse (priceIsInRange2 (null)); }

Den tidligere fremgangsmåde lover at kontrollere prisintervallet, men skal gøre mere end det for at forsvare sig mod dets iboende skrøbelighed. Derfor kan vi bruge filter metode til at erstatte unødvendig hvis udsagn og afvise uønskede værdier.

11. Transformere værdi med kort()

I det forrige afsnit kiggede vi på, hvordan man afviser eller accepterer en værdi baseret på et filter.

Vi kan bruge en lignende syntaks til at transformere Valgfri værdi med kort() metode:

@Test offentligt ugyldigt givetOptional_whenMapWorks_thenCorrect () {Vis firmaNames = Arrays.asList ("paypal", "oracle", "", "microsoft", "", "apple"); Valgfri listOptional = Optional.of (companyNames); int size = listOptional .map (List :: size) .orElse (0); assertEquals (6, størrelse); }

I dette eksempel pakker vi en liste over strenge inde i en Valgfri indvende og brug dens kort metode til at udføre en handling på den indeholdte liste. Den handling, vi udfører, er at hente størrelsen på listen.

Det kort metode returnerer resultatet af beregningen pakket ind indeni Valgfri. Vi skal derefter kalde en passende metode på den returnerede Valgfri for at hente dens værdi.

Bemærk, at filter metode udfører simpelthen en kontrol af værdien og returnerer en boolsk. Det kort metode tager dog den eksisterende værdi, udfører en beregning ved hjælp af denne værdi og returnerer resultatet af beregningen pakket ind i en Valgfri objekt:

@Test offentligt ugyldigt givetOptional_whenMapWorks_thenCorrect2 () {String name = "baeldung"; Valgfrit navnOptional = Optional.of (navn); int len ​​= nameOptional .map (String :: længde) .ellerElse (0); assertEquals (8, len); }

Vi kan kæde kort og filter sammen for at gøre noget mere magtfuldt.

Lad os antage, at vi vil kontrollere rigtigheden af ​​en adgangskodes indtastning af en bruger. Vi kan rense adgangskoden ved hjælp af en kort transformation og kontrollere dens rigtighed ved hjælp af en filter:

@Test offentligt ugyldigt givetOptional_whenMapWorksWithFilter_thenCorrect () {String password = "password"; Valgfri passOpt = Optional.of (adgangskode); boolsk correctPassword = passOpt.filter (pass -> pass.equals ("password")). isPresent (); assertFalse (correctPassword); correctPassword = passOpt .map (String :: trim) .filter (pass -> pass.equals ("password")) .isPresent (); assertTrue (correctPassword); }

Som vi kan se, bliver det filtreret ud uden først at rense inputet - alligevel kan brugerne tage for givet, at ledende og bageste rum alle udgør input. Så vi omdanner en beskidt adgangskode til en ren med en kort inden du filtrerer de forkerte ud.

12. Transformere værdi med flatMap ()

Ligesom kort() metode, har vi også flatMap () metode som et alternativ til transformation af værdier. Forskellen er, at kort transformerer kun værdier, når de pakkes ud, mens flatMap tager en indpakket værdi og pakker den ud, inden den transformeres.

Tidligere oprettede vi simple Snor og Heltal genstande til indpakning i en Valgfri eksempel. Imidlertid modtager vi ofte disse objekter fra en accessor til et komplekst objekt.

For at få et klarere billede af forskellen, lad os se på a Person objekt, der tager en persons detaljer som navn, alder og adgangskode:

offentlig klasse person {privat strengnavn; privat int alder privat strengadgangskode; public Optional getName () {return Optional.ofNullable (name); } offentlig Valgfri getAge () {return Optional.ofNullable (alder); } offentlig Valgfri getPassword () {return Optional.ofNullable (adgangskode); } // normale konstruktører og sættere}

Vi opretter normalt et sådant objekt og pakker det ind i et Valgfri objekt ligesom vi gjorde med String.

Alternativt kan det returneres til os ved en anden metodeopkald:

Person person = ny person ("john", 26); Valgfri personOptional = Optional.of (person);

Bemærk nu, at når vi pakker en Person objekt, det indeholder indeholdt Valgfri tilfælde:

@Test offentligt ugyldigt givetOptional_whenFlatMapWorks_thenCorrect2 () {Person person = ny person ("john", 26); Valgfri personOptional = Optional.of (person); Valgfri nameOptionalWrapper = personOptional.map (Person :: getName); Valgfrit navnOptional = nameOptionalWrapper.orElseThrow (IllegalArgumentException :: new); String name1 = nameOptional.orElse (""); assertEquals ("john", name1); String name = personOptional .flatMap (Person :: getName) .orElse (""); assertEquals ("john", navn); }

Her forsøger vi at hente navnets attribut for Person modsætter sig at udføre en påstand.

Bemærk hvordan vi opnår dette med kort() metode i den tredje erklæring, og læg derefter mærke til, hvordan vi gør det samme med flatMap () metode bagefter.

Det Person :: getName Metodehenvisning svarer til Streng :: trim opkald, vi havde i det foregående afsnit til oprydning af en adgangskode.

Den eneste forskel er det getName () returnerer en Valgfri snarere end en streng som det gjorde trimme() operation. Dette kombineret med det faktum, at en kort transformation omslutter resultatet i en Valgfri objekt, fører til en indlejret Valgfri.

Under brug kort() metode, derfor er vi nødt til at tilføje et ekstra opkald for at hente værdien, inden vi bruger den transformerede værdi. På denne måde Valgfri indpakningen fjernes. Denne operation udføres implicit under brug flatMap.

13. Lænkning Valgfris i Java 8

Nogle gange kan det være nødvendigt at få den første ikke-tomme Valgfri objekt fra et antal Valgfris. I sådanne tilfælde ville det være meget praktisk at bruge en metode som orElseOptional (). Desværre understøttes en sådan handling ikke direkte i Java 8.

Lad os først introducere et par metoder, som vi bruger i hele dette afsnit:

privat Optional getEmpty () {return Optional.empty (); } privat Valgfri getHello () {return Optional.of ("hej"); } privat Optional getBye () {return Optional.of ("farvel"); } privat Valgfri createOptional (String input) {if (input == null || "" .equals (input) || "tom" .equals (input)) {return Optional.empty (); } returner Optional.of (input); }

For at kæde flere Valgfri objekter og få den første ikke-tomme i Java 8, kan vi bruge Strøm API:

@Test offentlig ugyldighed givenThreeOptionals_whenChaining_thenFirstNonEmptyIsReturned () {Valgfri fundet = Stream.of (getEmpty (), getHello (), getBye ()) .filter (Valgfri :: isPresent) .map (Valgfri :: get) .findFirst (); assertEquals (getHello (), fundet); }

Ulempen ved denne tilgang er, at alle vores metoder udføres altid, uanset hvor en ikke-tom Valgfri vises i Strøm.

Hvis vi dovent vil evaluere de metoder, der sendes til Stream.of (), skal vi bruge metoden henvisning og Leverandør grænseflade:

@Test offentlig ugyldighed givenThreeOptionals_whenChaining_thenFirstNonEmptyIsReturnedAndRestNotEvaluated () {Valgfri fundet = Stream.<>> af (dette :: getEmpty, dette :: getHello, dette :: getBye) .map (Leverandør :: get) .filter (Valgfrit :: isPresent) .map (Valgfrit :: get) .findFirst (); assertEquals (getHello (), fundet); }

Hvis vi har brug for metoder, der tager argumenter, er vi nødt til at ty til lambda-udtryk:

@Test offentlig ugyldighed givenTwoOptionalsReturnedByOneArgMethod_whenChaining_thenFirstNonEmptyIsReturned () {Valgfri fundet = Stream.<>> af (() -> createOptional ("tom"), () -> createOptional ("hej")). kort (Leverandør :: get) .filter (Valgfri :: isPresent) .map (Valgfri :: get). findFirst (); assertEquals (createOptional ("hej"), fundet); }

Ofte vil vi returnere en standardværdi, hvis alle de kædede Valgfris er tomme. Vi kan gøre det bare ved at føje et opkald til ellers() eller orElseGet ():

@Test offentligt ugyldigt givenTwoEmptyOptionals_whenChaining_thenDefaultIsReturned () {Streng fundet = Stream.<>> af (() -> createOptional ("tom"), () -> createOptional ("tom")) .map (Leverandør :: get) .filter (Valgfri :: isPresent) .map (Valgfri :: get). findFirst () .orElseGet (() -> "standard"); assertEquals ("standard", fundet); }

14. JDK 9 Valgfri API

Udgivelsen af ​​Java 9 tilføjede endnu flere nye metoder til Valgfri API:

  • eller() metode til at levere en leverandør, der skaber et alternativ Valgfri
  • ifPresentOrElse () metode, der tillader udførelse af en handling, hvis Valgfri er til stede eller en anden handling, hvis ikke
  • strøm() metode til konvertering af en Valgfri til en Strøm

Her er den komplette artikel til yderligere læsning.

15. Misbrug af Valgfris

Lad os endelig se en fristende, men farlig måde at bruge Valgfris: passerer en Valgfri parameter til en metode.

Forestil dig, at vi har en liste over Person og vi vil have en metode til at søge gennem listen for personer med et givet navn. Vi vil også gerne have, at metoden matcher poster med mindst en bestemt alder, hvis den er specificeret.

Da denne parameter er valgfri, kommer vi med denne metode:

offentlig statisk liste søgning (liste personer, strengnavn, valgfri alder) {// Nul kontrol for personer og navn returnerer personer.stream () .filter (p -> p.getName (). er lig med (navn)) .filter (p -> p.getAge (). get ()> = age.orElse (0)) .collect (Collectors.toList ()); }

Derefter frigiver vi vores metode, og en anden udvikler forsøger at bruge den:

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

Nu udfører udvikleren sin kode og får en NullPointerException.Der er vi nødt til at nulstille vores valgfri parameter, der overvinder vores oprindelige formål med at ønske at undgå denne slags situation.

Her er nogle muligheder, vi kunne have gjort for at håndtere det bedre:

offentlig statisk Listesøgning (liste personer, strengnavn, heltal) {// Nul kontrol for personer og navn endelig Heltal ageFilter = alder! = null? alder: 0; returnere people.stream () .filter (p -> p.getName (). er lig med (navn)). filter (p -> p.getAge (). get ()> = ageFilter) .collect (Collectors.toList () ); }

Der er parameteren stadig valgfri, men vi håndterer den kun i en kontrol.

En anden mulighed ville have været at oprette to overbelastede metoder:

offentlig statisk liste søgning (liste personer, strengnavn) {return doSearch (personer, navn, 0); } offentlig statisk liste søgning (liste personer, strengnavn, int alder) {return doSearch (personer, navn, alder); } privat statisk liste doSearch (liste personer, strengnavn, int alder) {// Nul kontrol for personer og navn returnerer people.stream () .filter (p -> p.getName (). er lig med (navn)) .filter ( p -> p.getAge (). get (). intValue ()> = alder) .collect (Collectors.toList ()); }

På den måde tilbyder vi en klar API med to metoder til forskellige ting (selvom de deler implementeringen).

Så der er løsninger, der skal undgås at bruge Valgfris som metodeparametre. Hensigten med Java ved frigivelse Valgfri var at bruge det som en returtype, hvilket indikerer, at en metode kan returnere en tom værdi. Som en kendsgerning, praksis med at bruge Valgfri Som en metode frarådes endda nogle kodeinspektører.

16. Valgfri og serialisering

Som beskrevet ovenfor, Valgfri er beregnet til at blive brugt som en returtype. Det anbefales ikke at prøve at bruge det som en felttype.

Derudover ved brug af Valgfri i en serie, der kan serialiseres, vil resultere i en NotSerializableException. Vores artikel Java Valgfri som Returtype løser yderligere problemerne med serialisering.

Og i Brug Valgfri Med Jackson forklarer vi, hvad der sker, hvornår Valgfri felter serieres sammen med et par løsninger for at opnå de ønskede resultater.

17. Konklusion

I denne artikel dækkede vi de fleste af de vigtige funktioner i Java 8 Valgfri klasse.

Vi undersøgte kort nogle grunde til, at vi ville vælge at bruge Valgfri i stedet for eksplicit nulkontrol og validering af input.

Vi lærte også, hvordan man får værdien af ​​et Valgfri, eller en standard, hvis den er tom, med få(), ellers() og orElseGet () metoder (og så den vigtige forskel mellem de sidste to).

Så så vi, hvordan vi kunne transformere eller filtrere vores Valgfris med kort (), flatMap () og filter(). Vi diskuterede hvad flydende APIValgfri tilbyder, da det giver os mulighed for let at kæde de forskellige metoder.

Endelig så vi hvorfor bruge Valgfris som metodeparametre er en dårlig idé, og hvordan man undgår det.

Kildekoden til alle eksempler i artiklen er tilgængelig på GitHub.