Útmutató a Java 8-hoz Választható

1. Áttekintés

Ebben az oktatóanyagban megmutatjuk a Választható osztály, amelyet a Java 8-ban vezettek be.

Az osztály célja egy típusú szintű megoldás biztosítása az opcionális értékek helyett nulla hivatkozások.

Hogy mélyebben megértsük, miért kell törődnünk a Választható osztályban, nézze meg az Oracle hivatalos cikkét.

2. Teremtés Választható Tárgyak

Az alkotásnak többféle módja van Választható tárgyakat.

Üres létrehozásához Választható objektum, egyszerűen használnunk kell azt üres() statikus módszer:

@Test public void whenCreatesEmptyOptional_thenCorrect () {Opcionális üres = Opcionális.empty (); assertFalse (üres.isPresent ()); }

Vegye figyelembe, hogy a jelen van() módszer annak ellenőrzésére, hogy van-e érték a Választható tárgy. Egy érték csak akkor van jelen, ha létrehoztunk Választható egy nemnulla érték. Megnézzük a jelen van() módszer a következő szakaszban.

Készíthetünk egy Választható objektum a statikus módszerrel nak,-nek():

@Test public void givenNonNull_whenCreatesNonNullable_thenCorrect () {String name = "baeldung"; Opcionális opció = Opcionális. (Név); assertTrue (opt.isPresent ()); }

Az érv azonban átment a nak,-nek() módszer nem lehet nulla. Ellenkező esetben kapunk egy NullPointerException:

@Test (várható = NullPointerException.class) public void givenNull_whenThrowsErrorOnCreate_thenCorrect () {String name = null; Opcionális. (Név); }

De abban az esetben, ha számítunk valamire nulla értékeket használhatjuk ofNullable () módszer:

@Test public void givenNonNull_whenCreatesNullable_thenCorrect () {String name = "baeldung"; Opcionális opció = Opcionális.Nullable (név); assertTrue (opt.isPresent ()); }

Ezzel, ha átmegyünk a nulla hivatkozás, nem dob kivételt, inkább üreset ad vissza Választható tárgy:

@Test public void givenNull_whenCreatesNullable_thenCorrect () {String name = null; Opcionális opció = Opcionális.Nem lehet (név); assertFalse (opt.isPresent ()); }

3. Az érték jelenlétének ellenőrzése: jelen van() és üres()

Amikor van egy Választható metódusból visszaküldött vagy általunk létrehozott objektumot ellenőrizhetjük, hogy van-e benne érték vagy sem jelen van() módszer:

@Test public void givenOptional_whenIsPresentWorks_thenCorrect () {Opcionális opció = Opcionális.of ("Baeldung"); assertTrue (opt.isPresent ()); opt = Opcionális.Nullable (null); assertFalse (opt.isPresent ()); }

Ez a módszer visszatér igaz ha a becsomagolt érték nem nulla.

A Java 11-től kezdve az ellenkezőjét is megtehetjük a üres módszer:

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

4. Feltételes fellépés ifPresent ()

A ifPresent () A módszer lehetővé teszi számunkra, hogy futtassunk egy kódot a becsomagolt értéken, ha kiderül, hogy nemnulla. Előtt Választható, tennénk:

if (név! = null) {System.out.println (név.hossz ()); }

Ez a kód ellenőrzi, hogy a név változó-e nulla vagy sem, mielőtt elindítanánk rajta valamilyen kódot. Ez a megközelítés hosszadalmas, és nem ez az egyetlen probléma - hajlamos a tévedésre is.

Valójában mi garantálja, hogy a változó kinyomtatása után nem fogjuk újra és újra használni elfelejtette végrehajtani a null ellenőrzést?

Ennek eredményeként a NullPointerException futás közben, ha egy null érték utat talál a kódba. Ha egy program bemeneti problémák miatt meghiúsul, az gyakran rossz programozási gyakorlatok eredménye.

Választható arra késztet minket, hogy a jó programozási gyakorlatok érvényesítésének módjaként kifejezetten a nullázhatatlan értékekkel foglalkozzunk.

Most nézzük meg, hogyan lehetne visszafejleszteni a fenti kódot a Java 8-ban.

A tipikus funkcionális programozási stílusban végrehajthatunk egy műveletet egy valóban jelen lévő objektumon:

@Test public void givenOptional_whenIfPresentWorks_thenCorrect () {Opcionális opció = Opcionális.of ("baeldung"); opt.ifPresent (név -> System.out.println (név.hossz ())); }

A fenti példában csak két kódsort használunk az első példában szereplő öt helyettesítésére: egy sor az objektumot egy Választható objektumot és a következőt implicit érvényesítés végrehajtására, valamint a kód végrehajtására.

5. Alapértelmezett érték With különben()

A különben() metódust használjuk egy Választható példa. Ehhez egy paraméter szükséges, amely alapértelmezett értékként működik. A különben() A metódus visszaadja a becsomagolt értéket, ha van, és az argumentuma egyébként:

@Test public void whenOrElseWorks_thenCorrect () {String nullName = null; Karakterlánc neve = Opcionális.Nullable (nullNév) .VagyElse ("john"); assertEquals ("john", név); }

6. Alapértelmezett érték With vagyElseGet ()

A vagyElseGet () módszer hasonló különben(). Azonban ahelyett, hogy egy értéket adna vissza, ha a Választható az érték nincs, szállítói funkcionális felületet igényel, amely meghívásra kerül, és visszaadja az invokáció értékét:

@Test public void whenOrElseGetWorks_thenCorrect () {String nullName = null; Karakterlánc neve = Opcionális.Nullable (nullNév) .VagyElseGet (() -> "john"); assertEquals ("john", név); }

7. Különbség különben és vagyElseGet ()

Sok programozónak, akik még újak Választható vagy Java 8, a különbség különben() és vagyElseGet () Nem tiszta. Valójában ez a két módszer azt a benyomást kelti, hogy funkcionalitásukban átfedik egymást.

Van azonban egy finom, de nagyon fontos különbség a kettő között, amely drasztikusan befolyásolhatja kódunk teljesítményét, ha nem jól értjük.

Hozzunk létre egy úgynevezett módszert getMyDefault () a teszt osztályban, amely nem vesz fel argumentumokat, és visszaad egy alapértelmezett értéket:

public String getMyDefault () {System.out.println ("Alapértelmezett érték beolvasása"); return "Alapértelmezett érték"; }

Lássunk két tesztet, és figyeljük meg mellékhatásukat, hogy megállapítsuk mindkettőt hol különben() és vagyElseGet () átfedések és ahol eltérnek:

@Test public void whenOrElseGetAndOrElseOverlap_thenCorrect () {String text = null; String defaultText = Optional.ofNullable (text) .orElseGet (this :: getMyDefault); assertEquals ("Alapértelmezett érték", defaultText); defaultText = Optional.ofNullable (text) .orElse (getMyDefault ()); assertEquals ("Alapértelmezett érték", defaultText); }

A fenti példában egy null szöveget tekerünk egy Választható objektumot és megkísérli megszerezni a becsomagolt értéket a két megközelítés mindegyikének felhasználásával.

A mellékhatás:

Alapértelmezett érték lekérése ... Alapértelmezett érték lekérése ...

A getMyDefault () metódust hívják meg minden esetben. Így történik amikor a becsomagolt érték nincs jelen, akkor mindkettő különben() és vagyElseGet () pontosan ugyanúgy működjenek.

Most futtassunk egy másik tesztet, ahol az érték jelen van, és ideális esetben az alapértelmezett értéket nem is szabad létrehozni:

@Test public void whenOrElseGetAndOrElseDiffer_thenCorrect () {String text = "Jelen van a szöveg"; System.out.println ("Az orElseGet használata:"); String defaultText = Optional.ofNullable (text) .orElseGet (this :: getMyDefault); assertEquals ("Jelenlegi szöveg", defaultText); System.out.println ("Az orElse használata:"); defaultText = Optional.ofNullable (text) .orElse (getMyDefault ()); assertEquals ("Jelenlegi szöveg", defaultText); }

A fenti példában már nem csomagoljuk a nulla értéket, és a kód többi része változatlan marad.

Most nézzük meg a kód futtatásának mellékhatásait:

Az orElseGet használata: Az orElse használata: Alapértelmezett érték beolvasása ...

Használat közben vegye figyelembe vagyElseGet () a becsomagolt érték lekéréséhez, a getMyDefault () metódust nem is hívják meg, mivel a benne lévő érték jelen van.

Használatakor azonban különben(), függetlenül attól, hogy a becsomagolt érték van-e vagy sem, létrejön az alapértelmezett objektum. Tehát ebben az esetben most létrehoztunk egy felesleges objektumot, amelyet soha nem használunk.

Ebben az egyszerű példában nincs alapértelmezett objektum létrehozásának jelentős költsége, mivel a JVM tudja, hogyan kell ilyenekkel foglalkozni. Amikor azonban olyan módszer, mint getMyDefault () webszolgálati hívást kell kezdeményeznie, vagy akár lekérdeznie kell egy adatbázist, a költség nagyon nyilvánvalóvá válik.

8. Kivételek With vagyElseThrow ()

A vagyElseThrow () módszer következik különben() és vagyElseGet () és új megközelítést ad hozzá a hiányzó érték kezeléséhez.

Az alapértelmezett érték visszaadása helyett, amikor a becsomagolt érték nincs, kivételt dob:

@Test (várható = IllegalArgumentException.class) public void whenOrElseThrowWorks_thenCorrect () {String nullNév = null; Karakterlánc neve = Optional.ofNullable (nullNév) .orElseThrow (IllegalArgumentException :: new); }

A Java 8 metódus-referenciái itt jól jönnek, hogy átadják a kivétel konstruktort.

A Java 10 bemutatta a leegyszerűsített no-arg verzióját vagyElseThrow () módszer. Üres esetén Választható dob egy NoSuchElelementException:

@Test (várható = NoSuchElementException.class) public void whenNoArgOrElseThrowWorks_thenCorrect () {String nullNév = null; Karakterlánc neve = Opcionális.Nullable (nullNév) .VagyElseThrow (); }

9. Visszatérő érték a kap()

A becsomagolt érték lekérésének végső megközelítése a kap() módszer:

@Test public void givenOptional_whenGetsValue_thenCorrect () {Opcionális opció = Opcionális.of ("baeldung"); Karakterlánc neve = opt.get (); assertEquals ("baeldung", név); }

Az előző három megközelítéstől eltérően azonban kap() csak akkor adhat vissza értéket, ha a becsomagolt objektum nem nulla; különben nem hoz ilyen elem kivételeket:

@Test (várható = NoSuchElementException.class) public void givenOptionalWithNull_whenGetThrowsException_thenCorrect () {Opcionális opcionális = Opcionális.FNullable (null); Karakterlánc neve = opt.get (); }

Ez a kap() módszer. Ideális esetben Választható segítene elkerülni az ilyen előre nem látható kivételeket. Ezért ez a megközelítés ellentétes a Választható és valószínűleg egy későbbi kiadásban elavul.

Tehát ajánlatos a többi változatot használni, amelyek lehetővé teszik számunkra a felkészülést és a kifejezett kezelését nulla ügy.

10. Feltételes visszatérés szűrő()

Futtathatunk inline tesztet becsomagolt értékünkön a szűrő módszer. Az állítmány argumentumként veszi fel, és egy Választható tárgy. Ha a becsomagolt érték túlhaladja az állítást, akkor a Választható olyan állapotban kerül vissza.

Ha azonban az állítmány visszatér hamis, akkor egy üreset ad vissza Választható:

@Test public void whenOptionalFilterWorks_thenCorrect () {Egész év = 2016; Opcionális év: Opcionális = Opcionális. (Év); logikai is2016 = yearOptional.filter (y -> y == 2016) .isPresent (); assertTrue (is2016); logikai is2017 = évOptional.filter (y -> y == 2017) .isPresent (); assertFalse (is2017); }

A szűrő A módszert általában a becsomagolt értékek elutasítására használják egy előre meghatározott szabály alapján. Használhatnánk egy rossz e-mail formátumot vagy egy nem elég erős jelszót.

Nézzünk meg egy másik értelmes példát. Tegyük fel, hogy modemet akarunk vásárolni, és csak az ára érdekel.

Leküldéses értesítéseket kapunk a modem árairól egy adott webhelyről, és ezeket objektumokban tároljuk:

nyilvános osztályú modem {privát Dupla ár; nyilvános modem (Dupla ár) {this.price = price; } // szokásos mérőeszközök és beállítók}

Ezután ezeket az objektumokat betápláljuk valamilyen kódba, amelynek egyetlen célja annak ellenőrzése, hogy a modem ára belül van-e a költségvetési tartományunkban.

Vessünk egy pillantást a kódra anélkül Választható:

nyilvános logikai árIsInRange1 (modem modem) {logikai isInRange = hamis; if (modem! = null && modem.getPrice ()! = null && (modem.getPrice ()> = 10 && modem.getPrice () <= 15)) {isInRange = true; } return isInRange; }

Figyeljen arra, hogy ennek eléréséhez mekkora kódot kell írnunk, különösen a ha feltétel. Az egyetlen része a ha az alkalmazás szempontjából kritikus feltétel az utolsó árkategóriás ellenőrzés; az ellenőrzések többi része védekező:

@Test public void whenFiltersWithoutOptional_thenCorrect () {assertTrue (priceIsInRange1 (új modem (10.0))); assertFalse (priceIsInRange1 (új modem (9.9))); assertFalse (priceIsInRange1 (új modem (null))); assertFalse (priceIsInRange1 (új modem (15.5))); assertFalse (priceIsInRange1 (null)); }

Ettől eltekintve el lehet felejteni a nullnapos ellenőrzéseket egy hosszú nap alatt anélkül, hogy fordítási időbeli hibákat tapasztalna.

Most nézzünk meg egy változatot a Opcionális # szűrő:

nyilvános logikai árIsInRange2 (Modem modem2) {return Opcionális.Nullable (modem2) .térkép (Modem :: getPrice) .szűrő (p -> p> = 10) .szűrő (p -> p <= 15) .isPresent (); }

A térkép A hívást egyszerűen arra használják, hogy egy értéket valamilyen más értékgé alakítsanak. Ne feledje, hogy ez a művelet nem módosítja az eredeti értéket.

Esetünkben egy árobjektumot kapunk a Modell osztály. Megnézzük a térkép() módszert részletesen a következő szakaszban.

Először is, ha a nulla objektum átkerül erre a módszerre, nem számítunk problémára.

Másodszor, az egyetlen logika, amelyet a testébe írunk, pontosan az, amit a módszer neve leír - ártartomány-ellenőrzés. Választható gondoskodik a többiről:

@Test public void whenFiltersWithOptional_thenCorrect () {assertTrue (priceIsInRange2 (új modem (10.0))); assertFalse (priceIsInRange2 (új modem (9.9))); assertFalse (priceIsInRange2 (új modem (null))); assertFalse (priceIsInRange2 (új modem (15.5))); assertFalse (priceIsInRange2 (null)); }

Az előző megközelítés az ártartomány ellenőrzését ígéri, de ennél többet kell tennie a benne rejlő törékenység ellen. Ezért használhatjuk a szűrő módszer a felesleges pótlására ha állításokat és elutasítja a nem kívánt értékeket.

11. Az érték átalakítása a térkép()

Az előző szakaszban megvizsgáltuk, hogyan lehet egy értéket elutasítani vagy elfogadni egy szűrő alapján.

Hasonló szintaxist használhatunk a Választható érték a térkép() módszer:

@Test public void givenOptional_whenMapWorks_thenCorrect () {List companyNames = Arrays.asList ("paypal", "oracle", "", "microsoft", "", "apple"); Választható listOptional = Opcionális.of (cégnév); int méret = listaOptional .map (List :: size) .orElse (0); assertEquals (6, méret); }

Ebben a példában egy stringek listáját tekerjük egy Választható objektum és használja annak térkép módszer egy művelet végrehajtására a tartalmazott listán. A művelet a lista méretének lekérése.

A térkép A metódus a belé csomagolt számítás eredményét adja vissza Választható. Ezután megfelelő módszert kell meghívnunk a visszaküldöttre Választható hogy lekérje az értékét.

Figyeljük meg, hogy a szűrő A módszer egyszerűen ellenőrzi az értéket, és visszaadja az a értéket logikai. A térkép A módszer azonban felveszi a meglévő értéket, ennek az értéknek a felhasználásával végez számítást, és visszaadja a számítás eredményét egy Választható tárgy:

@Test public void givenOptional_whenMapWorks_thenCorrect2 () {String name = "baeldung"; Opcionális nameOptional = Opcionális.of (név); int len ​​= névOptional .map (String :: length) .orElse (0); assertEquals (8, len); }

Láncolhatunk térkép és szűrő együtt valami erőteljesebb dolgot tenni.

Tegyük fel, hogy ellenőrizni akarjuk a felhasználó által beírt jelszó helyességét. Tisztíthatjuk a jelszót az a használatával térkép transzformációt és ellenőrizze annak helyességét a segítségével szűrő:

@Test public void givenOptional_whenMapWorksWithFilter_thenCorrect () {String password = "jelszó"; Opcionális passOpt = Opcionális.of (jelszó); logikai korrektPassword = passOpt.filter (pass -> pass.equals ("jelszó")). isPresent (); assertFalse (correctPassword); correctPassword = passOpt .map (String :: trim) .filter (pass -> pass.equals ("jelszó")) .isPresent (); assertTrue (correctPassword); }

Mint láthatjuk, a bemenet elõzetes megtisztítása nélkül kiszûrõdik - a felhasználók mégis természetesnek tekinthetik, hogy a vezetõ és a záró szóköz mind bemenetnek számít. Tehát a piszkos jelszót egy tiszta jelszóvá alakítjuk térkép mielőtt kiszűrné a helyteleneket.

12. Az érték átalakítása a flatMap ()

Akárcsak a térkép() módszer, megvan a flatMap () módszer az értékek transzformálásának alternatívájaként. A különbség az térkép csak akkor alakítja át az értékeket, ha kibontják őket flatMap átvesz egy becsomagolt értéket és kicsomagolja, mielőtt átalakítja.

Korábban egyszerűt hoztunk létre Húr és Egész szám tárgyak egy Választható példa. Azonban gyakran kapjuk ezeket az objektumokat egy összetett objektum hozzáférőjétől.

Ahhoz, hogy tisztább képet kapjon a különbségről, vessünk egy pillantást a Személy objektum, amely egy személy adatait, például nevét, életkorát és jelszavát tartalmazza:

public class Személy {private String név; privát int kor; privát karakterlánc jelszó; public Opcionális getName () {return Optional.ofNullable (név); } public Opcionális getAge () {return Optional.ofNullable (kor); } public Opcionális getPassword () {return Optional.ofNullable (jelszó); } // normál kivitelezők és beállítók}

Rendszerint létrehozunk egy ilyen objektumot, és becsomagoljuk egy Választható objektum, csakúgy, mint Stringgel.

Alternatív megoldásként visszaküldheti nekünk egy másik módszerrel:

Személy személy = új Személy ("john", 26); Opcionális személy Opcionális = Opcionális. (Személy);

Most vegye észre, hogy amikor becsomagolunk egy Személy objektum, beágyazottakat fog tartalmazni Választható példányok:

@Test public void givenOptional_whenFlatMapWorks_thenCorrect2 () {Személy = új Személy ("john", 26); Opcionális személy Opcionális = Opcionális. (Személy); Választható nameOptionalWrapper = personOptional.map (Személy :: getName); Opcionális nameOptional = névOptionalWrapper.orElseThrow (IllegalArgumentException :: new); Karakterlánc neve1 = névOptional.orElse (""); assertEquals ("john", név1); Karakterlánc neve = personOptional .flatMap (Person :: getName) .orElse (""); assertEquals ("john", név); }

Itt megpróbáljuk beolvasni a. Név attribútumát Személy objektum egy állítás végrehajtására.

Jegyezzük meg, hogyan érjük el ezt térkép() metódust a harmadik állításban, majd vegye észre, hogyan csináljuk ugyanezt flatMap () módszer utólag.

A Személy :: getName módszer referenciája hasonló a Karakterlánc :: trim hívás volt az előző szakaszban a jelszó tisztítására.

Az egyetlen különbség az getName () visszatér egy Választható nem pedig húr, mint ahogy a trim () művelet. Ez párosulva azzal, hogy a térkép az átalakítás az eredményt egy Választható objektum, beágyazotthoz vezet Választható.

Használat közben térkép() metódust, ezért hozzá kell adnunk egy extra hívást az érték lekéréséhez, mielőtt az átalakított értéket használnánk. Így a Választható a burkolatot eltávolítjuk. Ezt a műveletet implicit módon hajtják végre a használat során flatMap.

13. Láncolás Választhatós a Java 8-ban

Előfordulhat, hogy az első nem üreset kell megkapnunk Választható objektum számos Választhatós. Ilyen esetekben nagyon kényelmes lenne olyan módszert használni, mint a vagyElseOptional (). Sajnos az ilyen műveleteket a Java 8 nem támogatja közvetlenül.

Először mutassunk be néhány módszert, amelyeket ebben a szakaszban fogunk használni:

privát Opcionális getEmpty () {return Opcionális.empty (); } privát Opcionális getHello () {return Optional.of ("hello"); } privát Opcionális getBye () {return Optional.of ("viszlát"); } privát Opcionális createOptional (String input) {if (input == null || "" .equals (input) || "empty" .equals (input)) {return Opcionális.empty (); } return Opcionális.of (input); }

Annak érdekében, hogy több láncoljon Választható objektumokat és megkapjuk az első nem üreset a Java 8-ban, használhatjuk a Folyam API:

@Test public void givenThreeOptionals_whenChaining_thenFirstNonEmptyIsReturned () {Opcionális talált = Stream.of (getEmpty (), getHello (), getBye ()) .filter (Opcionális :: isPresent) .map (Opcionális :: get) .findFirst (); assertEquals (getHello (), talált); }

Ennek a megközelítésnek az a hátránya, hogy mindannyian kap a módszereket mindig végrehajtják, függetlenül attól, hogy hol van egy nem üres Választható megjelenik a Folyam.

Ha lustán ki akarjuk értékelni az átadott módszereket Stream.of (), a metódus referenciát és a Támogató felület:

@Test public void givenThreeOptionals_whenChaining_thenFirstNonEmptyIsReturnedAndRestNotEvaluated () {Opcionális talált = Patak.<>> (ennek: getEmpty, ennek :: getHello, ennek :: getBye) .map (Szállító :: get) .filter (Opcionális :: isPresent) .map (Opcionális :: get) .findFirst (); assertEquals (getHello (), talált); }

Abban az esetben, ha argumentumokat tartalmazó módszereket kell használnunk, lambda-kifejezésekhez kell folyamodnunk:

@Test public void givenTwoOptionalsReturnedByOneArgMethod_whenChaining_thenFirstNonEmptyIsReturned () {Opcionális talált = Patak.<>> / (() -> createOptional ("üres"), () -> createOptional ("hello")) .map (Beszállító :: get) .filter (Opcionális :: isPresent) .map (Opcionális :: get). findFirst (); assertEquals (createOptional ("hello"), talált); }

Gyakran vissza akarunk adni egy alapértelmezett értéket, ha az összes láncolva van Választhatós üresek. Csak hívás hozzáadásával tehetjük meg különben() vagy vagyElseGet ():

@Test public void givenTwoEmptyOptionals_whenChaining_thenDefaultIsReturned () {String found = Stream.<>> / (() -> createOptional ("üres"), () -> createOptional ("üres")) .map (Beszállító :: get) .filter (Opcionális :: isPresent) .map (Opcionális :: get). findFirst () .orElseGet (() -> "alapértelmezett"); assertEquals ("alapértelmezett", talált); }

14. JDK 9 Választható API

A Java 9 kiadása még több új módszert adott a Választható API:

  • vagy() alternatívát teremtő szállító biztosításának módszere Választható
  • ifPresentOrElse () metódus, amely lehetővé teszi egy művelet végrehajtását, ha a Választható jelen van, vagy más akció, ha nem
  • folyam() metódus egy Választható a Folyam

Itt található a teljes cikk további olvasáshoz.

15. A következőkkel való visszaélés Választhatós

Végül lássunk egy csábító, bármennyire veszélyes felhasználási módot is Választhatós: elhaladni egy Választható paraméter egy metódushoz.

Képzelje el, hogy van egy listánk Személy és egy módszert akarunk keresni a listán az adott névvel rendelkező emberek után. Azt is szeretnénk, ha ez a módszer megfelelne a bejegyzéseknek legalább egy bizonyos életkorral, ha ez meg van határozva.

Mivel ez a paraméter nem kötelező, ezzel a módszerrel érkezünk:

nyilvános statikus Lista keresése (Személyek felsorolása, Karakterlánc neve, Választható életkor) {// Az emberek és a név vissza nem térít ellenőrzése emberek.stream () .filter (p -> p.getName (). egyenlő (név)) .filter (p -> p.getAge (). get ()> = age.orElse (0)) .collect (Collectors.toList ()); }

Ezután kiadjuk a módszerünket, és egy másik fejlesztő megpróbálja használni:

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

Most a fejlesztő végrehajtja a kódját, és megkapja a NullPointerException.Ott állunk, hogy nulláznunk kell az opcionális paraméterünket, amely meghiúsítja kezdeti célunkat azáltal, hogy el akarjuk kerülni ezt a fajta helyzetet.

Íme néhány lehetőség, amelyet megtehettünk volna a jobb kezelés érdekében:

nyilvános statikus Lista keresése (Személyek felsorolása, Karakterlánc neve, Egész életkor) {// Nullellenőrzések az emberek és a név végleges egészére ageFilter = age! = null? életkor: 0; return people.stream () .filter (p -> p.getName (). egyenlő (név)) .filter (p -> p.getAge (). get ()> = ageFilter) .collect (Collectors.toList () ); }

A paraméter továbbra is opcionális, de csak egy ellenőrzés alatt kezeljük.

Egy másik lehetőség az lett volna hozzon létre két túlterhelt módszert:

nyilvános statikus Lista keresése (Személyek felsorolása, Karakterlánc neve) {return doSearch (emberek, név, 0); } public static List search (Személyek felsorolása, String neve, int kor) {return doSearch (emberek, név, életkor); } private static List doSearch (Személyek felsorolása, Karakterlánc neve, int kor) {// Az emberek és a név nem ellenőrzi az embereket.stream () .filter (p -> p.getName (). egyenlő (név)) .filter ( p -> p.getAge (). get (). intValue ()> = kor) .collect (Collectors.toList ()); }

Így világos API-t kínálunk két módszerrel, amelyek különböző dolgokat végeznek (bár megosztják a megvalósítást).

Tehát vannak megoldások a használat elkerülésére Választhatós mint módszer paraméterei. A Java szándéka a kiadáskor Választható visszatérési típusként kellett használni, ezzel jelezve, hogy egy módszer üres értéket adhat vissza. Ami azt illeti, a használat gyakorlata Választható mivel a metódus paraméterét néhány kódellenőr még el is bátortalanítja.

16. Választható és a sorosítás

Amint fentebb említettük, Választható visszatérési típusként szolgál. Nem ajánlott megpróbálni mezőtípusként használni.

Ezenkívül felhasználásával Választható egy sorozható osztályban a NotSerializableException. Cikkünk Java Választható mivel a Return Type tovább foglalkozik a sorozatosítással kapcsolatos problémákkal.

És a Használatban Választható Jacksonnal elmagyarázzuk, mi történik, amikor Választható a mezők sorosak, néhány megkerüléssel a kívánt eredmények elérése érdekében.

17. Következtetés

Ebben a cikkben a Java 8 fontos jellemzőinek többségét ismertettük Választható osztály.

Röviden megvizsgáltunk néhány okot, amiért választanánk a felhasználást Választható kifejezett nullellenőrzés és bemeneti ellenőrzés helyett.

Megtanultuk azt is, hogyan lehet az an értékét megszerezni Választható, vagy alapértelmezett, ha üres, a kap(), különben() és vagyElseGet () módszereket (és látta a fontos különbséget az utóbbi kettő között).

Aztán láttuk, hogyan lehet átalakítani vagy szűrni a sajátunkat Választhatós vele térkép (), flatMap () és szűrő(). Megbeszéltük, milyen folyékony APIVálasztható kínál, mivel ez lehetővé teszi számunkra a különböző módszerek egyszerű láncolását.

Végül láttuk, miért használjuk Választhatós mivel a módszer paraméterei rossz ötlet, és hogyan lehet ezt elkerülni.

A cikk összes példájának forráskódja elérhető a GitHubon.