Lombok Using @With Annotations | Baeldung

文章推薦指數: 80 %
投票人數:10人

Learn how to make copies of immutable objects with changes to only a single property using Lombok. StartHereCourses ▼▲ RESTwithSpring(30%off) ThecanonicalreferenceforbuildingaproductiongradeAPIwithSpring LearnSpringSecurity(30%off) ▼▲ THEuniqueSpringSecurityeducationifyou’reworkingwithJavatoday LearnSpringSecurityCore(30%off) FocusontheCoreofSpringSecurity5 LearnSpringSecurityOAuth(30%off) FocusonthenewOAuth2stackinSpringSecurity5 LearnSpring(30%off) Fromnoexperiencetoactuallybuildingstuff​ LearnSpringDataJPA(30%off) ThefullguidetopersistencewithSpringDataJPA Guides ▼▲ Persistence ThePersistencewithSpringguides REST TheguidesonbuildingRESTAPIswithSpring Security TheSpringSecurityguides About ▼▲ FullArchive Thehighleveloverviewofallthearticlesonthesite. BaeldungEbooks DiscoverallofoureBooks AboutBaeldung AboutBaeldung. MarchDiscountLaunch2022 We’refinallyrunningaspringlaunch.AllCoursesare30%offuntilnextFriday: >>GETACCESSNOW 1.Introduction LombokisalibrarythathelpsussignificantlyreduceboilerplatecodewhenwritingJavaapplications. Inthistutorial,we'llseehowwecanmakecopiesofimmutableobjectswithchangestoonlyasinglepropertyusingthislibrary. 2.Usage Whenworkingwithimmutableobjects,whichbydesigndon'tallowsetters,wemayneedasimilarobjecttothecurrentone,butwithonlyonepropertydifferent.ThiscanbeachievedusingLombok's@Withannotation: publicclassUser{ privatefinalStringusername; privatefinalStringemailAddress; @With privatefinalbooleanisAuthenticated; //getters,constructors } Theaboveannotationgeneratesthefollowingunderthehood: publicclassUser{ privatefinalStringusername; privatefinalStringemailAddress; privatefinalbooleanisAuthenticated; //getters,constructors publicUserwithAuthenticated(booleanisAuthenticated){ returnthis.isAuthenticated==isAuthenticated?this:newUser(this.username,this.emailAddress,isAuthenticated); } } Wecanthenusetheabove-generatedmethodtocreatemutatedcopiesoftheoriginalobject: UserimmutableUser=newUser("testuser","[email protected]",false); UserauthenticatedUser=immutableUser.withAuthenticated(true); assertNotSame(immutableUser,authenticatedUser); assertFalse(immutableUser.isAuthenticated()); assertTrue(authenticatedUser.isAuthenticated()); Additionally,wehavetheoptionofannotatingthewholeclass,whichwillgeneratewithX() methodsforalltheproperties. 3.Requirements Tousethe@Withannotationcorrectly,weneedtoprovideanall-argumentsconstructor.Aswecanseefromtheaboveexample,thegeneratedmethodrequiresthistocreateacloneoftheoriginalobject. WecanuseeitherLombok'sown@AllArgsConstructoror@Valueannotationtosatisfythisrequirement.Alternatively,wecanmanuallyprovidethisconstructoraswellwhileensuringthattheorderofthenon-staticpropertiesintheclassmatchesthatoftheconstructor. Weshouldrememberthatthe@Withannotationdoesnothingifusedonstaticfields.Thisisbecausestaticpropertiesarenotconsideredpartofanobject'sstate.Also,Lombokskipsthemethodgenerationforfieldsthatstartwiththe$sign. 4.AdvancedUsage Let'sinvestigatesomeadvancedscenarioswhenusingthisannotation. 4.1.AbstractClasses Wecanusethe@Withannotationonafieldofanabstractclass: publicabstractclassDevice{ privatefinalStringserial; @With privatefinalbooleanisInspected; //getters,constructor } However,wewillneedtoprovideanimplementationforthegeneratedwithInspected() method.Thisisbecause Lombokwillhavenoideaabouttheconcreteimplementationsofourabstractclasstocreateclonesofit: publicclassKioskDeviceextendsDevice{ @Override publicDevicewithInspected(booleanisInspected){ returnnewKioskDevice(getSerial(),isInspected); } //getters,constructor } 4.2.NamingConventions Asweidentifiedabove,Lombokwillskipfieldsthatstartwiththe$sign.However,ifthefieldstartswithacharacter,thenitistitle-cased,andfinally,withisprefixedtothegeneratedmethod. Alternatively,ifthefieldstartswithanunderscore,thenwithissimplyprefixedtothegeneratedmethod: publicclassHolder{ @With privateStringvariableA; @With privateString_variableB; @With privateString$variableC; //getters,constructorexcluding$variableC } Accordingtotheabovecode,weseethatonlythefirsttwovariables willhavewithX() methodsgeneratedforthem: Holdervalue=newHolder("a","b"); HoldervalueModifiedA=value.withVariableA("mod-a"); HoldervalueModifiedB=value.with_variableB("mod-b"); //HoldervalueModifiedC=value.with$VariableC("mod-c");notpossible 4.3.ExceptionstoMethodGeneration Weshouldbemindfulthatinadditiontofieldsthatstartwiththe$sign,LombokwillnotgenerateawithX() methodifitalreadyexistsinourclass: publicclassStock{ @With privateStringsku; @With privateintstockCount; //preventsanotherwithSku()methodfrombeinggenerated publicStockwithSku(Stringsku){ returnnewStock("mod-"+sku,stockCount); } //constructor } Intheabovescenario,nonewwithSku()methodwillbegenerated. Additionally,Lombokskipsmethodgenerationinthefollowingscenario: publicclassStock{ @With privateStringsku; privateintstockCount; //alsopreventsanotherwithSku()methodfrombeinggenerated publicStockwithSKU(String...sku){ returnsku==null||sku.length==0? newStock("unknown",stockCount): newStock("mod-"+sku[0],stockCount); } //constructor } WecannoticethedifferentnamingofthewithSKU()methodabove. Basically,Lombokwillskipmethodgenerationif: Thesamemethodexistsasthegeneratedmethodname(ignoringcase) Theexistingmethodhasthesamenumberofargumentsasthegeneratedmethod(includingvar-args) 4.4.NullValidationsonGeneratedMethods SimilartootherLombokannotations,wecanincludenullcheckstothemethodsgeneratedusingthe@Withannotation: @With @AllArgsConstructor publicclassImprovedUser{ @NonNull privatefinalStringusername; @NonNull privatefinalStringemailAddress; } Lombokwillgeneratethefollowingcodeforusalongwiththerequirednullchecks: publicImprovedUserwithUsername(@NonNullStringusername){ if(username==null){ thrownewNullPointerException("usernameismarkednon-nullbutisnull"); }else{ returnthis.username==username?this:newImprovedUser(username,this.emailAddress); } } publicImprovedUserwithEmailAddress(@NonNullStringemailAddress){ if(emailAddress==null){ thrownewNullPointerException("emailAddressismarkednon-nullbutisnull"); }else{ returnthis.emailAddress==emailAddress?this:newImprovedUser(this.username,emailAddress); } } 5.Conclusion Inthisarticle,wehaveseenhowtouseLombok's@Withannotationstogenerateclonesofaparticularobjectwithachangeinasinglefield. Wealsolearnedhowandwhenthismethodgenerationactuallyworks,alongwithhowtoaugmentitwithadditionalvalidationssuchasnullchecks. Asalways,thecodeexamplesareavailableoveronGitHub. MarchDiscountLaunch2022 We’refinallyrunningaspringlaunch.AllCoursesare30%offuntilnextFriday: >>GETACCESSNOW Genericfooterbanner LearningtobuildyourAPIwithSpring? DownloadtheE-book Commentsareclosedonthisarticle! LaunchDiscount30% OnAllCourses VIEWDETAILS Followthe Java Category FollowtheJavacategorytogetregularinfoaboutthenewarticlesandtutorialswepublishhere. FOLLOWTHEJAVACATEGORY



請為這篇文章評分?