Project Lombok: Clean, Concise Java Code - Oracle

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

The Lombok library was created to make Java an easier language in which to code. It takes some of the most common boilerplate headaches out of the developer's ... ClicktoviewourAccessibilityPolicy Skiptocontent home nav Oracle Close Search Search Products Industries Resources Support Events Developer Partners ViewAccountsSignIn Back OracleAccount CloudAccount SignintoCloud SignUpforFreeCloudTier Sign-In CreateanAccount Help SignOut ContactSales Noresultsfound Yoursearchdidnotmatchanyresults. Wesuggestyoutrythefollowingtohelpfindwhatyou’relookingfor: Checkthespellingofyourkeywordsearch. Usesynonymsforthekeywordyoutyped,forexample,try“application”insteadof“software.” Tryoneofthepopularsearchesshownbelow. Startanewsearch. TrendingQuestions Close   AboutOracle   JavaDeveloper|Libraries ProjectLombok:Clean,ConciseJavaCode AddLomboktoyourprojectandgetridofmostofyourboilerplatecode. ByJoshJuneau ImaginethatyouarecodingaJavaapplicationandcreatingaplainoldJavaobject(POJO),aJavaclasswithseveralprivatefieldsthatwillrequiregetterandsettermethodstoprovideaccess.Howmanylinesofcodewillbeneededtogenerate gettersandsettersforeachofthefields?Moreover,addingaconstructorandatoString()methodwillcauseevenmorelinesofcodeandclutter.Thatisalotofboilerplatecode.HowaboutwhenyouareutilizingJavaobjectsthatneedtobeclosedafteruse,soyouneedtocodeafinallyblockorusetry-with-resourcestoensurethattheobjectclosingoccurs?Addingfinallyblockboilerplatetocloseobjectscanaddasignificantamountofcluttertoyourcode. ProjectLombokisamaturelibrarythatreducesboilerplatecode.ThecasesmentionedabovecoverjustafewofthosewhereProjectLombokcanbeagreatbenefit.Thelibraryreplacesboilerplatecodewitheasy-to-useannotations.Inthisarticle,IexamineseveralusefulfeaturesthatProjectLombokprovides—makingcodeeasiertoreadandlesserror-proneandmakingdevelopersmoreproductive.Bestofall,thelibraryworkswellwithpopularIDEsandprovidesautilityto“delombok”yourcodebyreverting—thatis,addingbackalltheboilerplatethatwasremovedwhentheannotationswereadded. CheckforNulls Let’sstartwithoneofthemostbasicutilitiesthatLombokhastooffer.The@NonNullannotation,whichshouldnotbeconfusedwiththeBeanValidationannotation,canbeusedtogenerateanullcheckonasetterfield.ThecheckthrowsaNullPointerExceptioniftheannotatedclassfieldcontainsanullvalue.Simplyapplyittoafieldtoenforcetherule: @NonNull@Setter privateStringemployeeId; Thiscodegeneratesthefollowingcode: publicidsetEmployeeId(@NonNullfinalStringemployeeId) { if(employeeId==null)throw newjava.lang.NullPointerException("employeeId"); this.employeeId=employeeId; [email protected],awarningisissuedandnonullcheckisgenerated. ConciseDataObjects WritingaPOJOcanbelaborious,especiallyiftherearemanyfields.IfyouaredevelopingaPOJO,youshouldalwaysprovideprivateaccessdirectlytotheclassfields,whilecreatingaccessormethods—gettersandsetters—toreadfromandwritetothosefields.Althoughdevelopingaccessormethodsiseasy,theygenerallyarejustboilerplatecode.Lombokcantakecareofgeneratingthesemethodsifafieldisannotatedwith@[email protected],thefollowingtwocodelistingsprovidetheexactsamefunctionality. WithoutProjectLombok: privateStringcolumnName; publicStringgetColumnName(){ returnthis.columnName; } publicvoidsetColumnName(StringcolumnName){ this.columnName=columnName; } UsingProjectLombok: @Getter@SetterprivateStringcolumnName; Asyoucansee,Lomboknotonlymakesthecodemoreconcise,butitalsomakesthecodeeasiertoreadandlesserror-prone.Theseannotationsalsoacceptanoptionalparametertodesignatetheaccesslevelifneeded.Moregoodnews:@Getterand@Setterrespectthepropernamingconventions,sogeneratedcodeforaBooleanfieldresultsinaccessormethodsbeginningwithisratherthanget.Iftheyareappliedattheclasslevel,gettersandsettersaregeneratedforeachnonstaticfieldwithintheclass.  Lombokcantakecareoftheloggerdeclarationifyouplacethe@Logannotation(oranannotationpertainingtoyourchoiceofloggingAPI)onanyclassthatrequiresloggingcapability.  Inmanycases,dataobjectsalsoshouldcontaintheequals(),hashCode(),andtoString()methods.Thisboilerplatecanbetakencareofbyannotatingaclasswiththe@EqualsAndHashCodeand@ToStringannotations,respectively.TheseannotationscauseLomboktogeneratetherespectivemethods,andtheyarecustomizablesothatyoucanspecifyfieldexclusionsandotherfactors.Bydefault,anynonstaticornontransientfieldsareincludedinthelogicthatisusedtocomposethesemethods.Theseannotationsusetheattributeexcludetospecifymethodsthatshouldnotbeincludedinthelogic.ThecallSuperattributeacceptsatrueorfalse,anditindicateswhethertousetheequals()methodofthesuperclasstoverifyequality.Thefollowingcodedemonstratestheuseoftheseannotations. @EqualsAndHashCode @ToString(exclude={"columnLabel"}) publicclassColumnBean{ privateBigDecimalid; privateStringcolumnName; privateStringcolumnLabel; } The@Dataannotationcanbeusedtoapplyfunctionalitybehindalltheannotationsdiscussedthusfarinthissection.Thatis,simplyannotatingaclasswith@DatacausesLomboktogenerategettersandsettersforeachofthenonstaticclassfieldsandaclassconstructor,aswellasthetoString(),equals(),andhashCode()methods.Italsocreatesaconstructorthatacceptsanyfinalfieldsorthoseannotatedwith@NonNullasarguments.Finally,itgeneratesdefaulttoString(),equals(),andhashCode()methodsthattakeallclassfieldsandmethodsintoconsideration.ThismakesthecodingofaPOJOveryeasy,anditismuchthesameassomealternativelanguages,suchasGroovy,thatoffersimilarfeatures.Listing1(alllistingsforthisarticlecanbefoundinJavaMagazine’sdownloadsection)showsthefullJavacodeforthePOJOthatisgeneratedbythefollowingcode: @Data publicclassColumnBean{ @NonNull privateBigDecimalid; @NonNull privateStringcolumnName; @NonNull privateStringcolumnLabel; } Notethatifyoucreateyourowngettersorsetters,Lombokdoesnotgeneratethecodeeveniftheannotationsarepresent.Thiscanbehandyifyouwishtodevelopacustomgetterorsetterforoneormoreoftheclassfields. Ifyouaremerelyinterestedinhavingconstructorsgeneratedautomatically,@AllArgsConstructorand@NoArgsConstructormightbeofuse.@AllArgsConstructorcreatesaconstructorfortheclassusingallthefieldsthathavebeendeclared.Ifafieldisaddedorremovedfromtheclass,thegeneratedconstructorisrevisedtoaccommodatethischange.Thisbehaviorcanbeconvenientforensuringthataclassconstructoralwaysacceptsvaluesforeachoftheclassfields.Thedisadvantageofusingthisannotationisthatreorderingtheclassfieldscausestheconstructorargumentstobereorderedaswell,whichcouldintroducebugsifthereiscodethatdependsuponthepositionofargumentswhengeneratingtheobject.@NoArgsConstructorsimplygeneratesano-argumentconstructor. The@Valueannotationissimilartothe@Dataannotation,butitgeneratesanimmutableclass.Theannotationisplacedattheclasslevel,anditinvokestheautomaticgenerationofgettersforallprivatefinalfields.Nosettersaregenerated,andtheclassismarkedasfinal.Lastly,thetoString(),equals(),andhashCode()methodsaregenerated,andaconstructorisgeneratedthatcontainsargumentsforeachofthefields. Can’tMyIDEDoThat? Youmightbeaskingyourself,“Can’tmyIDEalreadydothatsortofrefactoring?”MostmodernIDEs—suchasNetBeans,Eclipse,andIntelliJ—offerfeaturessuchasencapsulationoffieldsandauto-generationofcode.Theseabilitiesaregreatbecausetheycansignificantlyincreaseproductivity.However,thesecapabilitiesdonotreducecodeclutter,sotheycanleadtorefactoringdowntheroad.Let’ssayyourJavaobjecthas10fields.ToconformtoaJavaBean,itwillcontain20accessormethods(onegetterandsetterpairperfield).That’salotofclutter.Also,whathappenswhenyoudecidetochangeoneofyourfieldnames?You’llhavetodosomerefactoringinordertochangeitcleanly.Ifyou’reusingLombok,yousimplychangethefieldnameandmoveonwithyourlife. BuilderObjects Sometimesitisusefultohavetheabilitytodevelopabuilderobject,whichallowsobjectstobeconstructedusingastep-by-steppatternwithcontrolledconstruction.Forexample,insomecaseslargeobjectsrequireseveralfieldstobepopulated,whichcanbeproblematicwhensuchanobjectisimplementedviaaconstructor. LombokmakesitsimpletocreatebuilderobjectsinmuchthesamewaythatitenableseasyPOJOcreation.Annotatingaclasswith@Builderproducesaclassthatadherestothebuilderpattern—thatis,aninnerbuilderclassisproducedthatcontainseachoftheclassfields.(“Builder”isprecededbythenameoftheclass.SoaclassnamedFoohasaFooBuilderclassgenerated.)Thegeneratedbuilderclasscontainsa“setter”methodforeachoftheclassfields,butthenamesofthemethodsdonotincludetheusual“set”prefix.Themethodsthemselvessetthevaluethatispassedintothemethods,andthentheyreturnthebuilderobject.Listing2inthedownloadablecodedemonstratesaclassthatcontainsabuilder,andListing3demonstratesthesameobjectannotatedwith@Builder. [email protected],theannotationcanbeplacedontheclass,onaconstructor,oronamethod.PlacingtheannotationonaconstructorproducesthesamebuilderobjectshowninListing2,butitgeneratesmethodsforeachoftheconstructor’sargumentsinthebuilder.Thismeansthatyoucanomitaclassfieldfromtheconstructor,oryoucanchoosetoincludeasuperclassfieldintheconstructor.Theonlywaytoincludesuperclassfieldsinabuilderisforanobjecttocontainasuperclass. ThetoBuilderattributeofthe@Builderannotationacceptstrueorfalse,anditcanbeusedtodesignatewhetheratoBuilder()methodisincludedinthegeneratedbuilderobject.Thismethodcopiesthecontentsofanexistingobjectofthesametype. Itispossibletotreatoneofthefieldsasabuildercollectionbyannotatingitwith@Singular.Thiscausestwoaddermethodstobegenerated—onetoaddasingleelementandanothertoaddallelements.Thisannotationalsocausesaclear()methodtobegenerated,whichclearsthecontentsofthecollection. EasyCleanup Lombokmakesiteasytocleanupresourcesaswell.Howoftenhaveyoueitherforgottentoclosearesourceorwrittenlotsofboilerplatetry-catchblockstoaccommodateresourceclosing?Thankstothe@Cleanupannotation,younolongerneedtoworryaboutforgettingtoreleasearesource. AlthoughtheJavalanguagenowcontainsthetry-with-resourcesstatementtohelpcloseresources,@Cleanupcanbeausefulalternativeinsomecases,becauseitcausesatry-finallyblocktobegeneratedaroundthesubsequentcode,andthenitcallstheannotatedresource’sclose()method.Ifthecleanupmethodforagivenresourceisnotnamedclose(),thecleanupmethodnamecanbespecifiedwiththeannotation’svalueattribute.Listing4inthedownloadablecodedemonstratesablockofcodethatcontainssomelinestomanuallyclosetheresource.Listing5demonstratesthesameblockofcodeusing@Cleanup. Itisimportanttonotethatinacasewherecodethrowsanexceptionandthensubsequentcodeinvokedvia@Cleanupalsothrowsanexception,theoriginalexceptionwillbehiddenbythesubsequentlythrownexception. LockingSafely Toensuresafetybyhavingonlyonethreadthatcanaccessaspecifiedmethodatatime,themethodshouldbemarkedassynchronized.Lomboksuppliesanevensaferwaytoensurethatonlyonethreadcanaccessamethodatatime:the@Synchronizedannotation.Thisannotationcanbeusedonlyonstaticandinstancemethods,justlikethesynchronizedkeyword.However,ratherthanlockingonthis,theannotationlocksonaprivatefieldnamed$lockfornonstaticmethodsandon$LOCKforstaticmethods.Thisfieldisauto-generatedifitdoesnotalreadyexist,oryoucancreateityourself.Youcanalsospecifyadifferentlockfieldbyspecifyingitasaparameterto@Synchronized.Thefollowingcodeillustratestheuseof@Synchronized: @Synchronized publicstaticvoidhelloLombok(){ System.out.println("Lombok"); } Thissolutioncanbeasaferalternativetousingthesynchronizedkeyword,becauseitallowsyoutolockonaninstancefieldratherthanonthis. EffortlessLogging Mostloggingrequiressomedeclarationtosetupaloggerwithineachclass.Thiscodeisdefinitelyrepetitiveboilerplatecode.Lombokcantakecareoftheloggerdeclarationifyouplacethe@Logannotation(oranannotationpertainingtoyourchoiceofloggingAPI)onanyclassthatrequiresloggingcapability. Forinstance,ifyouwishtousealoggingAPI—say,Log4j2—eachclassthatusestheloggermustdeclaresomethingsimilartothefollowing: publicclassClassName(){ privatestaticfinalorg.apache.log4j.Loggerlog= org.apache.log4j.Logger.getLogger(ClassName.class); ... //Uselogvariableasneeded } Lombokmakesitpossibletodothefollowinginstead: @Log4j2 publicclassClassName(){ ... //Uselogvariableasneeded } Listing6inthedownloadablecodeshowsanexampleusingLog4j2.Thenameoftheloggerwillautomaticallybethesameasitscontainingclass’name.However,thiscanbecustomizedbyspecifyingthetopicattributeoftherespectiveloggingannotation.ForacompletelistingofsupportedloggingAPIs,refertotheLombokdocumentationandtheLombokJavadoc. OtherUsefulItems ThereareseveralotherusefulfeaturesLombokoffersthatIhaven’tyetcovered.Let’sgothroughacoupleofthemosthighlyused. Informaldeclaration.Thevalkeywordcanbeusedinplaceofanobjecttypewhenyoudeclarealocalfinalvariable,muchlikethevalkeywordthatyouhaveseeninalternativelanguagessuchasGroovyorJython.Takethefollowingcode,forinstance: finalArrayListmyJobs=newArrayList(); Usingthevalkeyword,youcanchangethecodetothefollowing: valmyJobs=newArrayList(); Therearesomeconsiderationsforusingthevalkeyword.First,asmentionedpreviously,itmarksthemethoddeclarationasfinal.Therefore,ifyoulaterneedtochangethevalueofthevariable,usingthevalkeywordisnotpossible.ItalsodoesnotworkcorrectlyinsomeIDEs,soifyouaretryingtomarklocalvariablesasfinalinthoseIDEs,theyareflaggedaserrors. Besneakywithexceptions.Thereareoccasionswhereexceptionhandlingcanbecomeaburden,andI’darguethatthisistypicallythecasewhenyouareworkingwithboilerplateexceptions.Mostofthetime,Javaallowsyoutoeasilyseewhereproblemsexistviatheuseofcheckedexceptions.However,inthosecaseswherecheckedexceptionsareburdensome,youcaneasilyhidethemusingLombok.  ThedelombokutilitycanbeappliedtoyourcodetoconvertcodethatusesLombokbacktovanillaJava.  The@SneakyThrowsannotationcanbeplacedonamethodtoessentially“swallow”theexceptions,allowingyoutoomitthetry-catchblockcompletely.Theannotationallowsamethodtohandleallexceptionsquietly,oryoucanspecifyexactlywhichexceptionstoignorebypassingtheexceptionclassestotheannotationasattributes.Listing7inthedownloadablecodedemonstratestheuseof@SneakyThrowsspecifyingwhichexceptionstoswallow. IwanttoreiteratethatthisLombokfeatureshouldbeusedwithcaution,becauseitcanbecomearealissueiftoomanyexceptionsareignored. Lazygetters.Itispossibletoindicatethatafieldshouldhaveagettercreatedonce,andthentheresultshouldbecachedforsubsequentinvocations.Thiscanbeusefulifyourgettermethodisexpensiveasfarasperformancegoes.Forinstance,ifyouneedtopopulatealistfromadatabasequery,oryouneedtoaccessawebservicetoobtainthedataforyourfieldonthefirstaccess,itmightmakesensetocachetheresultforsubsequentcalls.Tousethisfeature,aprivatefinalvariablemustbegeneratedandinitializedwiththeexpensiveexpression.Youcanthenannotatethefieldwith@Getter(lazy=true)toimplementthisfunctionality. IDEcompatibility.LombokplayswellwiththemajorIDEs,sosimplyincludingLombokinyourprojectandannotatingaccordinglytypicallydoesnotgenerateerrorsincodeorcauseerrorswhenthegeneratedmethodsarecalled.Infact,inNetBeanstheclassNavigatorispopulatedwiththegeneratedmethodsafterannotationsareplacedandthecodeissaved,eventhoughthemethodsdonotappearinthecode.Auto-completionworksjustasifthemethodsweretypedintotheclass,evenwhengeneratedpropertiesareaccessedfromawebviewinexpressionlanguage. Evenmore-conciseJavaEE.Overthepastfewyears,JavaEEhasbeenmakinggoodheadwayonbecomingaveryproductiveandconciseplatform.ThoseofyouwhorecallthelaboriousJ2EEplatformcancertainlyattesttothegreatnumberofimprovementsthathavebeenmade.IwasveryhappytolearnthatLombokplaysnicelywithsomeJavaEEAPIs,suchasJavaPersistenceAPI(JPA).Thismeansitisveryeasytodevelopconstructssuchasentityclasseswithoutwritingalltheboilerplate,whichmakestheclassesmuchmoreconciseandlesserror-prone.I’vedevelopedentireJavaEEapplicationswithoutanygettersorsettersinmyentityclasses,justbyannotatingthemwith@Data.Isuggestyouplayaroundwithitandseewhatworksbestforyou. Usecautionandrollback.Aswiththeuseofanylibrary,therearesomecaveatstokeepinmind.Thisisespeciallytruewhenyouarethinkingaboutfuturemaintenanceormodificationstothecodebase.Lombokgeneratescodeforyou,butthatmightcauseaproblemwhenitcomestorefactoring.Itisdifficulttorefactorcodethatdoesnotexistuntilcompiletime,sobecautiouswithrefactoringcodethatusesLombok.Youalsoneedtothinkaboutreadability.Lombokannotationsmightmaketroubleshootingamysteryforsomeonewhoisnotfamiliarwiththelibrary—andevenforthosewhoare—ifsomethingsuchas@SneakyThrowsishidinganexception. Fortunately,Lombokmakesiteasytorollbackifyouneedto.ThedelombokutilitycanbeappliedtoyourcodetoconvertcodethatusesLombokbacktovanillaJava.ThisutilitycanbeusedviaAntorthecommandline. Conclusion TheLomboklibrarywascreatedtomakeJavaaneasierlanguageinwhichtocode.Ittakessomeofthemostcommonboilerplateheadachesoutofthedeveloper’stasklist.Itcanbeusefulformakingyourcodemoreconcise,reducingthechanceforbugs,andspeedingupdevelopmenttime.TryaddingLomboktooneofyourapplicationsandseehowmanylinesofcodeyoucancutout. ThisarticleoriginallywaspublishedinJavaMagazine. JoshJuneau(@javajuneau)isaJavaChampionandamemberoftheNetBeansDreamTeam.Heworksasanapplicationdeveloper,systemanalyst,anddatabaseadministrator.HeisafrequentcontributortoOracleTechnologyNetworkandJavaMagazine.JuneauhaswrittenseveralbooksonJavaandJavaEEforApress,andheisaJCPExpertGroupmemberforJSR372(JavaServerFaces[JSF]2.3)andJSR378(Portlet3.0BridgeforJSF2.2). LearnMore DownloadJavaMagazinecodelistings Contact Social SignUp We'reheretohelp EngageaSalesExpert 1-800-633-0738(US) HaveOracleCallYou GlobalContacts FindaPartner SupportDirectory FollowOracleCorporate Facebook Twitter LinkedIn GooglePlus Youtube OracleSocialMediaDirectory OracleRSSDirectory Signupbytopic SubscriptionCenter Resourcesfor Careers Developers Investors Partners Startups StudentsandEducators WhyOracle AnalystReports GartnerMQforERPCloud CloudEconomics CorporateResponsibility DiversityandInclusion SecurityPractices Learn Whatiscloudcomputing? WhatisCRM? WhatisDocker? WhatisKubernetes? WhatisPython? WhatisSaaS? What’sNew TryOracleCloudFreeTier OracleProductNavigator OracleandPremierLeague OracleRedBullRacing EmployeeExperiencePlatform OracleSupportRewards ContactUs USSales:+1.800.633.0738 Howcanwehelp? Subscribetoemails Events News Blogs Country/Region ©2022Oracle SiteMap Privacy/DoNotSellMyInfo AdChoices Careers Facebook Twitter LinkedIn YouTube



請為這篇文章評分?