Java valgfri som returtype

1. Introduktion

Det Valgfri type blev introduceret i Java 8. Det giver en klar og eksplicit måde at formidle budskabet om, at der muligvis ikke er en værdi uden brug nul.

Når du får en Valgfri returneringstype, vil vi sandsynligvis kontrollere, om værdien mangler, hvilket fører til færre NullPointerExceptions i applikationerne. Men den Valgfri type er ikke egnet alle steder.

Selvom vi kan bruge det, uanset hvor vi finder det passende, fokuserer vi i denne vejledning på nogle af de bedste fremgangsmåder ved brug Valgfri som returtype.

2. Valgfri som returtype

En Valgfri type kan være en returtype for de fleste metoder undtagen nogle scenarier, der diskuteres senere i vejledningen.

Det meste af tiden returnerer en Valgfri er bare fint:

offentlig statisk valgfri findUserByName (strengnavn) {User user = usersByName.get (name); Valgfri opt = Optional.ofNullable (bruger); returoptagelse; }

Dette er praktisk, da vi kan bruge Valgfri API i kaldemetoden:

offentlig statisk ugyldig ændring Brugernavn (String oldFirstName, String newFirstName) {findUserByFirstName (oldFirstName) .ifPresent (user -> user.setFirstName (newFirstName)); }

Det er også passende for en statisk metode eller hjælpemetode at returnere en Valgfri værdi. Der er dog mange situationer, hvor vi ikke skal vende tilbage en valgfri type.

3. Hvornår skal man ikke vende tilbage Valgfri

Fordi Valgfri er en indpaknings- og værdibaseret klasse, er der nogle operationer, der ikke kan gøres imod Valgfri objekt. Mange gange er det bare bedre at returnere den aktuelle type i stedet for en Valgfri type.

Generelt set for getters i POJO'er er det mere passende at returnere den aktuelle type, ikke en Valgfri type. Især er det vigtigt for enhedsbønner, datamodeller og DTO'er at have traditionelle getters.

Vi undersøger nogle af de vigtige brugssager nedenfor.

3.1. Serialisering

Lad os forestille os, at vi har en simpel enhed:

public class Sock implementer Serializable {Heltalsstørrelse; Valgfri par; // ... getters og setters}

Dette fungerer faktisk slet ikke. Hvis vi skulle prøve at serieisere dette, ville vi få en NotSerializableException:

ny ObjectOutputStream (ny ByteArrayOutputStream ()). writeObject (ny Sock ()); 

Og virkelig, mens du serierer Valgfri kan arbejde med andre biblioteker, det tilføjer bestemt, hvad der kan være unødvendig kompleksitet.

Lad os se på en anden anvendelse af den samme serialiseringsfejl, denne gang med JSON.

3.2. JSON

Moderne applikationer konverterer Java-objekter til JSON hele tiden. Hvis en getter returnerer en Valgfri type, vil vi højst sandsynligt se nogle uventede datastrukturer i den endelige JSON.

Lad os sige, at vi har en bønne med en valgfri egenskab:

privat streng fornavn; public Optional getFirstName () {return Optional.ofNullable (fornavn); } public void setFirstName (String firstName) {this.firstName = firstName; }

Så hvis vi bruger Jackson til at serieisere en forekomst af Valgfri, vi får:

{"firstName": {"present": true}} 

Men hvad vi virkelig vil have er:

{"firstName": "Baeldung"}

Så, Valgfri er smertefuldt ved brug af serier. Lad os derefter se på fætter til serialisering: at skrive data til en database.

3.3. JPA

I JPA skal getter, setter og felt have navn såvel som typeaftale. F.eks fornavn felt af typen Snor skal parres med en kaldet getter getFirstName der også returnerer en Snor.

At følge denne konvention gør flere ting enklere, herunder brug af refleksion af biblioteker som Hibernate, for at give os stor støtte til objektrelationskortlægning.

Lad os se på vores samme brugstilfælde af et valgfrit fornavn i en POJO.

Denne gang er det dog en JPA-enhed:

@Entity offentlig klasse UserOptionalField implementerer Serializable {@Id privat lang brugerId; privat Valgfri fornavn; // ... getters og setters}

Og lad os gå videre og prøve at fortsætte med det:

UserOptionalField-bruger = ny UserOptionalField (); user.setUserId (1l); user.setFirstName (Optional.of ("Baeldung")); entityManager.persist (bruger);

Desværre støder vi på en fejl:

Forårsaget af: javax.persistence.PersistenceException: [PersistenceUnit: com.baeldung.optionalReturnType] Kunne ikke oprette Hibernate SessionFactory ved org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.persistenceException (EntityManagerFiber_ManagerFiber .boot.internal.EntityManagerFactoryBuilderImpl.build (EntityManagerFactoryBuilderImpl.java:941) på org.hibernate.jpa.HibernatePersistenceProvider.createEntityManagerFactory (HibernatePersistenceProvider.java:56) ved javax.persent. persistence.Persistence.createEntityManagerFactory (Persistence.java:54) at com.baeldung.optionalReturnType.PersistOptionalTypeExample. (PersistOptionalTypeExample.java:11) Forårsaget af: org.hibernate.MappingException: Kunne ikke bestemme typen for: javation.il tabel: UserOptionalField, for kolonner: [org.hibernate.mapping.Column (firstName)]

Vi kunne prøve afviger fra denne standard. For eksempel kunne vi beholde ejendommen som en Snor, men skift getter:

@Column (nullable = true) privat streng fornavn; public Optional getFirstName () {return Optional.ofNullable (fornavn); }

Det ser ud til, at vi kunne have begge veje: have en Valgfri returtype for getter og et vedvarende felt fornavn.

Men nu, hvor vi er inkonsekvente med vores getter, setter og felt, bliver det sværere at udnytte JPA-standardindstillinger og IDE-kildekodeværktøjer.

Indtil JPA har elegant understøttelse af Valgfri type, skal vi holde os til den traditionelle kode. Det er enklere og bedre:

privat streng fornavn; // ... traditionel getter og setter

Lad os endelig se på, hvordan dette påvirker frontend - kontroller for at se, om det problem, vi støder på, lyder velkendt.

3.4. Udtrykssprog

Forberedelse af en DTO til front-end giver lignende vanskeligheder.

Lad os for eksempel forestille os, at vi bruger JSP-skabeloner til at læse vores Bruger Valgfrit DTO'er fornavn fra anmodningen:

Da det er en Valgfri, vi ser ikke ”Baeldung“. I stedet ser vi Snor repræsentation af Valgfri type:

Valgfri [Baeldung] 

Og dette er ikke et problem bare med JSP. Ethvert skabelonsprog, det være sig Velocity, Freemarker eller noget andet, skal tilføje support til dette. Indtil da, lad os fortsætte med at holde vores DTO'er enkle.

4. Konklusion

I denne vejledning har vi lært, hvordan vi kan returnere en Valgfri objekt, og hvordan man håndterer denne form for returværdi.

På den anden side har vi også lært, at der er mange scenarier, som det ville være bedre for os ikke at bruge Valgfri returtype for en getter. Mens vi kan bruge Valgfri skriv som et tip om, at der muligvis ikke er nogen værdi, der ikke er nul, skal vi være forsigtige med ikke at overforbruge Valgfri returneringstype, især i en getter af en enhedsbønne eller en DTO.

Kildekoden til eksemplerne i denne vejledning kan findes på GitHub.