You are on page 1of 48

3/24/2015

java|Java,SQLandjOOQ.

Java,SQLandjOOQ.
BestPracticesandLessonsLearnedfromWritingAwesomeJavaandSQLCode.Getsomehandsoninsightonwhats
behinddevelopingjOOQ.
Archive|javaRSSforthissection

March24,2015

injava,sql
Leaveacomment

jOOQvs.Hibernate:WhentoChooseWhich
HibernatehasbecomeadefactostandardintheJavaecosystem,andafterthefact,alsoanactualJavaEE
standardimplementationifstandardsmattertoyou(http://xkcd.com/927),andifyouputtheJCPonthe
samelevelwithISO,ANSI,IEEE,etc.
Thisarticledoesnotintendedtodiscussstandards,butvisions.Hibernate(http://hibernate.org)sharesJPAs
visionofORM.jOOQ(http://www.jooq.org)sharesSQLsvisionofpowerfulquerying,soforthesakeofthe
argument,letsuseHibernate/JPA/ORMinterchangeably,muchlikejOOQ/JDBC/SQL.
ThequestionwhyshouldanyonenotuseHibernatethesedaysalwaysshowsupfrequently
(https://groups.google.com/forum/#!topic/jooquser/gmBf6g6sdQA)preciselybecauseHibernateisade
factostandard,andthefirstframeworkchoiceinmanyotherframeworkssuchasGrails(whichusesGORM,
whichagainusesHibernate(https://grails.github.io/grailsdoc/latest/guide/GORM.html)).
However,evenGavinKing,thecreatorofHibernate,doesntbelievethatHibernateshouldbeusedfor
everything:

(https://plus.google.com/+GavinKing/posts/LGJU1NorAvY)
Ifthatsthecase,arethereanyobjectivedecisionhelpingpointsthatyoucouldconsider,whentousean
ORMandwhentouseSQL?

Discussingonahighlevel
http://blog.jooq.org/category/java/

1/48

3/24/2015

java|Java,SQLandjOOQ.

Firstoff,letsbringthisdiscussiontoahigherlevel.InsteadofdecidingbetweenHibernateandjOOQas
concreteimplementationsoftheirowndomains,letsthinkaboutORMvs.SQL,andtheirdifferentusecases.
WhendecidingbetweenanORM(e.g.Hibernate)andSQL(e.g.jOOQ),thedrivingquestionthatyoushould
askyourselfisnotthequestionofprojectcomplexity.Someofourmostdemandingcustomersareusing
jOOQonmediumsizedschemaswiththousandsoftables/views.Often,thoseschemasareextremely
normalisedandsometimesevendeployedonasmanyassixdifferentRDBMS.jOOQwasspecifically
designedtoworkinthesescenarios,whilekeepingthesimpleusecaseinmindaswell.
So,insteadofthinkingaboutprojectcomplexity,askyourselfthefollowingquestions:
1.Willyourdatamodeldriveyourapplicationdesign,orwillyourapplicationdesigndriveyourdata
model(s)?
Amainaspecthereisthequestionwhetheryoucareaboutyourdatabaseinthesenseofwhetherit
mightsurviveyourapplication.Veryoften,applicationscomeandgo.TheymayberewritteninPython/
JavaScript,etc.5yearsdowntheline.Oryouhavemultipleapplicationsaccessingthesamedatabase:
YourJavaapplication,somePerlscripts,storedprocedures,etc.Ifthisisthecase,databasedesignisa
priorityinyourproject,andjOOQworksextremelywellinthesesetups.
IfyoudontnecessarilycareaboutyourdatabaseinthesensethatyoujustwanttopersistyourJava
domainsomewhere,andthishappenstobearelationaldatabase,thenHibernatemightbeabetterchoice
atleastinearlystagesofyourproject,becauseyoucaneasilygenerateyourdatabaseschemafromyour
Entitymodel.
2.Willyoudomostlycomplexreadingandsimplewriting,orwillyouengageincomplexwriting?
SQLreallyshineswhenreadingiscomplex.Whenyoujoinmanytables,whenyouaggregatedatainyour
database,whenyoudoreporting,whenyoudobulkreadingandwriting.Youthinkofyourdatainterms
ofsettheory,e.g.yourdataasawhole.WritingCRUDwithSQLisboring,though.ThisiswhyjOOQalso
providesyouwithanActiveRecordstyleAPIthathandlestheboringparts,whenyoureoperatingon
singletables(Jasonmentionedthis).
If,however,yourwritingbecomescomplex,i.e.youhavetoloadacomplexobjectgraphwith20entities
involvedintomemory,performoptimisticlockingonit,modifyitinmanydifferentwaysandthen
persistitagaininonego,thenSQL/jOOQwillnothelpyou.ThisiswhatHibernatehasoriginallybeen
createdfor.

Opinion
Ibelievethatdataisforever.Youshould*always*assumethatyourdatabasesurvivesyourapplication.Itis
mucheasiertorewrite(partsof)anapplicationthantomigrateadatabase.Havingacleanandwelldesigned
databaseschemawillalwayspayoffdownthelineofaproject,specificallyofacomplexproject.Seealsoour
previousarticleaboutthefallacyofschemalessdatabases(http://blog.jooq.org/2014/10/20/stopclaiming
thatyoureusingaschemalessdatabase/).
Also,mostprojectsreallydo90%readingand10%writing,writingoftennotbeingcomplex(23tables
modifiedwithinatransaction).Thismeansthatmostofthetime,thecomplexitysolvedbyHibernate/JPAs
firstandsecondlevelcachesisnotneeded.Peopleoftenmisunderstandthesefeaturesandsimplyturnoff
caching,flushingHibernatescachetotheserverallthetime,andthususingHibernateinthewrongway.
http://blog.jooq.org/category/java/

2/48

3/24/2015

java|Java,SQLandjOOQ.

If,however,youreundecidedabouttheabovetwoaxesofdecision,youcangothemiddlewayanduse
jOOQonlyforreporting,batchprocessing,etc.anduseHibernateforyourCRUDinaCQRS(Command
QueryResponsibilitySegregation:http://martinfowler.com/bliki/CQRS.html
(http://martinfowler.com/bliki/CQRS.html))style.TherearealsoquiteafewjOOQuserswhohavechosen
thispath.

Furtherreading
Throughputvs.ComplexityWhenshouldIuseanORM?
(http://mikehadlow.blogspot.ca/2012/06/whenshouldiuseorm.html)byMikeHadlow
WhyshouldyouuseanORM?(http://karwin.blogspot.ch/2009/01/whyshouldyouuseorm.html)byBill
Karwin
ArethereanygoodreasonsnottouseanORM?(http://stackoverflow.com/q/194147/521799)onStack
Overflow
WhyshouldyouuseanORM?(http://stackoverflow.com/q/448684/521799)onStackOverflow

March13,2015
injava,java8
2Comments

10JavaArticlesEveryoneMustRead
Onemonthago,wevepublishedalistof10SQLArticlesEveryoneMustRead
(http://blog.jooq.org/2015/02/13/10sqlarticleseveryonemustread/).Alistofarticlesthatwebelievewould
addexceptionalvaluetoourreadersonthejOOQblog(http://blog.jooq.org).ThejOOQblogisablog
focusingonbothJavaandSQL,soitisonlynaturalthattoday,onemonthlater,werepublishinganequally
excitinglistof10Javaarticleseveryonemustread.
Notethatbymustread,wemaynotspecificallymeantheparticularlinkedarticleonly,butalsoother
worksfromthesameauthors,whohavebeenregularbloggersoverthepastyearsandneverfailedto
producenewinterestingcontent!
Heregoes

1.BrianGoetz:Stewardship:theSoberingParts
ThefirstblogpostisactuallynotablogpostbutarecordingofaveryinterestingtalkbyBrianGoetzon
OraclesstewardshipofJava.OnthejOOQblog,wevebeenslightlycriticalabout12featuresoftheJava
languageinthepast,e.g.whencomparingittoScala(http://blog.jooq.org/2014/08/01/the10mostannoying
http://blog.jooq.org/category/java/

3/48

3/24/2015

java|Java,SQLandjOOQ.

thingscomingbacktojavaaftersomedaysofscala/),orCeylon(http://blog.jooq.org/2013/12/03/top10
ceylonlanguagefeaturesiwishwehadinjava/).
BrianmakesgoodpointsaboutwhyitwouldnotbeagoodideaforJavatobecomejustasmodernas
quicklyasotherlanguages.AmustwatchforeveryJavadeveloper(around1h)

2.AlekseyShipilv:TheBlackMagicof(Java)Method
Dispatch
Inrecentyears,theJVMhasseenquiteafewimprovements,includinginvokedynamicthatarrivedinJava7
asaprerequisiteforJava8lambdas,aswellasagreattoolforother,moredynamiclanguagesbuiltontopof
theJVM,suchasNashorn(http://blog.jooq.org/2014/06/06/java8fridayjavascriptgoessqlwithnashorn
andjooq/).
invokedynamicisonlyasmall,highlevelpuzzlepieceintheadvancedtrickeryperformedbytheJVM.
Whatreallyhappensunderthehoodwhenyoucallmethods?Howaretheyresolved,optimisedbytheJIT?
Alekseysarticlesubtitlerevealswhatthearticleisreallyabout:
EverythingyouwantedtoknowaboutBlackDeviouslySurreptitiousMagicinlowlevelperformanceengineering
Definitelynotasimpleread,butagreatposttolearnaboutthepoweroftheJVM.
ReadAlekseysTheBlackMagicof(Java)MethodDispatch(http://shipilev.net/blog/2015/blackmagic
methoddispatch/)

3.OliverWhite:JavaToolsandTechnologiesLandscapefor
2014
http://blog.jooq.org/category/java/

4/48

3/24/2015

java|Java,SQLandjOOQ.

Werealreadyin2015,butthisreportbyOliverWhite(atthetimeheadofZeroTurnaroundsRebelLabs
(http://zeroturnaround.com/rebellabs/))hadbeenexceptionallywellexecutedandtouchesprettymuch
everythingrelatedtotheJavaecosystem.
ReadOliversJavaToolsandTechnologiesLandscapefor2014
(http://zeroturnaround.com/rebellabs/javatoolsandtechnologieslandscapefor2014/)

4.PeterLawrey:JavaLambdasandLowLatency
WhenAlekseyhasintroducedustosomeperformancesemanticsintheJVM,Petertakesthisonestep
further,talkingaboutlowlatencyinJava8.Wecouldhavepickedmanyotherusefullittleblogpostsfrom
Petersblog,whichisallaboutlowlatency,highperformancecomputingontheJVM,sometimesevendoing
advancedoffheaptrickery.
ReadPetersJavaLambdasandLowLatency(http://vanillajava.blogspot.ch/2015/01/javalambdasand
lowlatency.html)

5.NicolaiParlog:EverythingYouNeedToKnowAbout
DefaultMethods
NicolaiisanewcomerintheJavablogosphere,andaverypromisingone,too.Hiswellresearchedarticlesgo
indepthaboutsomeinterestingfactsrelatedtoJava8,diggingoutoldemailsfromtheexpertgroups
mailinglist,explainingthedecisionstheymadetoconcludewithwhatwecallJava8today.
ReadNicolaisEverythingYouNeedToKnowAboutDefaultMethods
(http://blog.codefx.org/jdk/everythingaboutdefaultmethods/)

6.LukasEder:10ThingsYouDidntKnowAboutJava
ThislistwouldntbecompletewithoutlistinganotherlistthatwewroteourselvesonthejOOQblog.Javais
anoldbeastwith20yearsofhistorythisyearin2015.Thisoldbeasthasalotofsecretsandcaveatsthat
manypeoplehaveforgottenorneverthoughtabout.Weveuncoveredthemforyou:
ReadLukass10ThingsYouDidntKnowAboutJava(http://blog.jooq.org/2014/11/03/10thingsyou
didntknowaboutjava/)

http://blog.jooq.org/category/java/

5/48

3/24/2015

java|Java,SQLandjOOQ.

7.EdwinDalorzo:WhyThereIsInterfacePollutioninJava8
Edwinhasbeenrespondingtoourownblogpostsacoupleoftimesinthepastwithverywellresearched
andthoroughlythoughtthrougharticles,inparticularaboutJava8relatedfeatures,e.g.comparingJava8
StreamswithLINQ(http://blog.informatech.cr/2013/03/24/javastreamspreviewvsnetlinq/)(somethingthat
wevedoneourselves,aswell(http://blog.jooq.org/2013/11/02/doesjava8stillneedlinqorisitbetterthan
linq/)).
Thisparticulararticleexplainswhytherearesomanydifferentanddifferentlynamedfunctionalinterfacesin
Java8.
ReadEdwinsWhyThereIsInterfacePollutioninJava8(http://blog.informatech.cr/2014/04/04/jdk8
interfacepollution/)

8.VladMihalcea:HowDoes
PESSIMISTIC_FORCE_INCREMENTLockModeWork
WhenJavatalkstodatabases,manypeopledefaulttousingHibernateforconvenience(seealso3.Oliver
White:JavaToolsandTechnologiesLandscapefor2014(http://zeroturnaround.com/rebellabs/javatoolsand
technologieslandscapefor2014/)).Hibernatesmainvision,however,isnottoaddconvenienceyoucan
getthatinmanyotherwaysaswell(http://www.hibernatealternative.com/).Hibernatesmainvisionisto
providepowerfulmeansofnavigatingandpersistinganobjectgraphrepresentationofyourRDBMSsdata
model,includingvariouswaysoflocking.
VladisanextremelyproficientHibernateuser,whohasawholeblogseriesonhowHibernateworksgoing.
Wevepickedarecent,wellresearchedarticleaboutlocking,butwestronglysuggestyoureadtheother
articlesaswell:
ReadVladsHowDoesPESSIMISTIC_FORCE_INCREMENTLockModeWork
(http://vladmihalcea.com/2015/02/16/hibernatelockingpatternshowdoespessimistic_force_increment
lockmodework/)

9.PetriKainulainen:WritingCleanTests
ThisisntapurelyJavarelatedblogpost,althoughitiswrittenfromtheperspectiveofaJavadeveloper.
Moderndevelopmentinvolvestestingautomatictestingandlotsofit.Petrihaswrittenaninterestingblog
seriesaboutwritingcleantestsinJavayoushouldntmisshisarticles!
ReadPetrisWritingCleanTests(http://www.petrikainulainen.net/writingcleantests/)
http://blog.jooq.org/category/java/

6/48

3/24/2015

java|Java,SQLandjOOQ.

10.EugenParaschiv:Java8ResourcesCollection
Ifyoudontalreadyhaveatleast9opentabswithinterestingstufftoreadafterthislist,getreadyfora
browsertabexplosion!EugenParaschivwhomaintainsbaeldung.com(http://baeldung.com)hasbeen
collectingallsortsofveryinterestingresourcesrelatedtoJava8inasinglelinkcollection.Youshould
definitelybookmarkthiscollectionandcheckbackfrequentlyforinterestingchanges:
ReadEugensJava8ResourcesCollection(http://www.baeldung.com/java8)

Manyotherarticles
Thereare,ofcourse,manyotherverygoodarticlesprovidingdeepinsightintousefulJavatricks.Ifyoufind
youveencounteredanarticlethatwouldnicelycomplementthislist,pleaseleavealinkanddescriptionin
thecommentssection.Futurereaderswillappreciatetheadditionalinsight.

March9,2015

injava,opensource
Leaveacomment

YakShavingisaGoodWaytoImproveanAPI
YakShaving(uncountable)(http://en.wiktionary.org/wiki/yak_shaving):
1. (idiomatic)Anyapparentlyuselessactivitywhich,byallowingyoutoovercomeintermediatedifficulties,
allowsyoutosolvealargerproblem.
2. (idiomatic)Alessusefulactivitydonetoconsciouslyorunconsciouslyprocrastinateaboutalargerbut
moreusefultask.
BothinterpretationsofthetermYakShavingasexplainedbyWiktionary
(http://en.wiktionary.org/wiki/yak_shaving)areabsolutelyaccuratedescriptionsofmostrefactoringjobs.The
YakShavinginrefactoringitselfcanbedescribedbythisgifshowingwhathappenswhenyouwantto
changealightbulb:

http://blog.jooq.org/category/java/

7/48

3/24/2015

java|Java,SQLandjOOQ.

(http://imgur.com/gallery/t0XHtgJ)
However,whendevelopinganAPI,itsnotsuchabadideatoperformactualYakShaving(onlythefirst
interpretation,ofcourse).Letslookatanexamplewhy,fromthedailyworkmaintainingjOOQ
(http://www.jooq.org).

TheTask
ForjOOQ3.6,Iwantedtoimplementaverysimplefeature.Feature#2639:AddstoredprocedureOUT
valuestoDEBUGlogoutput(https://github.com/jOOQ/jOOQ/issues/2639).Thisisnotanimportantfeatureat
all,butcertainlyveryusefultoalotofjOOQusers.Theideaisthateverytimeyourunastoredprocedure
withDEBUGloggingactivated,youllgettheOUTparametersloggedalongwiththeprocedurecall.Heresa
visualisation:

(https://lukaseder.files.wordpress.com/2015/03/debuglog.png)
Now,theactualimplementationwouldhavebeenveryeasy.Justabout10linesofcodeintheexisting
LoggerListener(http://www.jooq.org/javadoc/latest/org/jooq/tools/LoggerListener.html)thatalreadytakes
careofloggingalltheotherthings.Buttherewereacoupleofcaveats,whichremindedmeoftheabove
lightbulbchanginggif:

Theapparentlyuselessactivities
1. TherewasnowaytoaccesstheRETURN_VALUEmetainformationofajOOQRoutine
(http://www.jooq.org/javadoc/latest/org/jooq/Routine.html)
http://blog.jooq.org/category/java/

8/48

3/24/2015

java|Java,SQLandjOOQ.

2. TherewasnoeasywaytoaccessRoutineINandOUTvaluesgenerically
3. TherewaslifecycleeventthatmodelledthemomentwhenOUTparametersarefetchedinjOOQ
4. TherewasnowaytoformatRoutineOUTparametersinaniceway
Doesthisfeelfamiliar?Thereisneedforrefactoring!
Lukas Eder @lukaseder

02 Mar
Do you know that feeling? When you're implementing a really small
change and suddenly, in order to implement it nicely, you have 20
changes?

Jason Herr

Follow

@herr_jason

@lukaseder Someone sent this to me to explain it.


pic.twitter.com/ZBr06UlAir
9:11 AM 2 Mar 2015

1 RETWEET 2 FAVORITES

Now,thiswholeimplementationishiddeninjOOQsinternals.Itwouldntmattertoomuchforusers,ifthis
hadbeenhackedtogetherinonewayoranother.Forinstance,obviouslytheRETURN_VALUEmeta
informationcouldbeaccessedthroughinternalrefactorings,thesameistrueforINandOUTvalues.There
areotherlifecycleeventsthatmighthaveworkedjustaswell,andformattingiseasytoreimplement.
ButthisisapopularAPIthatisusedbymanyuserswhomightprofitfromacleanersolution.Thus,why
dontwesimplyrefactorandimplement:
1. AddapublicRoutine.getReturnParameter()method(https://github.com/jOOQ/jOOQ/issues/4107)
2. AddpublicRoutine.getValue()andsetValue()methods(https://github.com/jOOQ/jOOQ/issues/3748)
3. AddExecuteListener.outStart(ExecuteContext)andoutEnd(ExecuteContext)tocapturefetchingof
RoutineOUTparameters(https://github.com/jOOQ/jOOQ/issues/4108)
4. AddRoutine.outRecord()andRoutine.inRecord()toviewaRoutineasaRecord
(https://github.com/jOOQ/jOOQ/issues/4109)
Thethingis:
http://blog.jooq.org/category/java/

9/48

3/24/2015

java|Java,SQLandjOOQ.

TheAPIimplementoristhefirstAPIconsumer
ItshardtoforeseewhatAPIusersreallywant.ButifyoureimplementinganAPI(orjustafeature),andyou
discoverthatsomethingismissing,alwaysconsideraddingthatmissingthingtothepublicAPI.Ifitcouldbe
usefultoyourself,internally,itcouldbeevenmoreusefultomanyothers.Thisway,youturnonelittlenice
featureinto5,amplifyingtheuserlove.
Dontgetmewrong.Thisdoesntmeanthateverylittlepieceoffunctionalityneedstobeexposedpublicly,
aucontraire.Butthefactthatsomethingiskeepingyouasthemaintainerfromwritingcleancodemight
indicatethatothersimplementthesamehackyworkaroundsasyou.Andtheywontaskyouexplicitlyforit!
Dontbelieveit?Heresanentirelysubjectiveanalysisofuserfeedback:
0.2%Hey,thisisacoolproduct,Iwanttohelptheownermakeitbetter,Illprovideaverydescriptive,
constructivefeaturerequestandengageforthenext5weekstohelpimplementit.
0.8%Whateverdudes.Makethiswork.Please.
1.3%Whateverdudes.Makethiswork.ASAP!
4.0%WTFiswrongwithyouguys?Didntyouatleastthinkaboutthisonce??
4.7%OK,Imgoingtowritethiscompletelyuninformedrantaboutthisproductnow,whichIhateso
much.Itmakesmylifecompletelymiserable
9.0%Ohwell,thisdoesntwork.Letsgohome,its17:00anyways
80.0%Ohwell,thisdidntworkyesterdayalready.Letsgohome.ItsFriday,16:00anyways
Now,mostofthislistwasntmeantentirelyseriously,butyougetthepoint.Theremaybethose0.2%of
users/customersthatloveyouandthatactivelyengagewithyou.Othersmaystillloveyouoratleastlike
you,buttheywontengage.Youhavetoguesstimatewhattheyneed.
So.Bottomline:
Ifyouneedit,theyprobablyneedit.StartYakShaving!

March5,2015

injava
Leaveacomment

TheJavaLegacyisConstantlyGrowing
IverecentlystumbleduponaveryinterestingcaveatoftheJDKAPIs,theClass.getConstructors()
(http://docs.oracle.com/javase/8/docs/api/java/lang/Class.html#getConstructors)method.Itsmethod
signatureisthis:
Constructor<?>[]getConstructors()
http://blog.jooq.org/category/java/

10/48

3/24/2015

java|Java,SQLandjOOQ.

TheinterestingthinghereisthatClass.getConstructor(Class...)
(http://docs.oracle.com/javase/8/docs/api/java/lang/Class.html#getConstructorjava.lang.Class...)returnsa
Constructor<T>,with<T>beingmaintained:
Constructor<T>getConstructor(Class<?>...parameterTypes)
Whyisthereadifference,i.e.whydoesntthefirstmethodreturnConstructor<T>[]?
LetsconsidertheJavadoc:
NotethatwhilethismethodreturnsanarrayofConstructor<T>objects(thatisanarrayofconstructorsfromthis
class),thereturntypeofthismethodisConstructor<?>[]andnotConstructor<T>[]asmightbeexpected.Thisless
informativereturntypeisnecessarysinceafterbeingreturnedfromthismethod,thearraycouldbemodifiedtohold
Constructorobjectsfordifferentclasses,whichwouldviolatethetypeguaranteesofConstructor<T>[].

Thatsatoughone.Historically,hereshowthishappened:
Java1.0/Oak:Arrays
InJava1.0(theimmediatesuccessoroftheOakprogramminglanguage
(https://en.wikipedia.org/wiki/Oak_(programming_language))),arrayswerealreadyintroduced.Infact,they
havebeenintroducedbeforethecollectionsAPI,whichwasintroducedinJava1.2.Arrayssufferfromallthe
problemsthatweknowtoday,includingthembeingcovariant,whichleadstoalotofproblemsatruntime,
thatcannotbecheckedatcompiletime:
Object[]objects=newString[1];
objects[0]=Integer.valueOf(1);//Ouch

http://blog.jooq.org/category/java/

11/48

3/24/2015

java|Java,SQLandjOOQ.

Java1.1:ReflectionAPI
ShortofadecentcollectionsAPI,theonlypossiblereturntypeoftheClass.getConstructors()method
wasConstructor[].Areasonabledecisionatthetime.Ofcourse,youcoulddothesamemistakeasabove:
Object[]objects=String.class.getConstructors();
objects[0]=Integer.valueOf(1);//Ouch
butintheadditiontotheabove,youcouldalso,rightfully,writethis:
Constructor[]constructors=String.class.getConstructors();
constructors[0]=Object.class.getConstructor();
//Muahahahahahahaha
Java1.2:CollectionsAPI
Javahasbeenbackwardscompatiblefromtheveryearlydays,evenfromOakonwards.Theresavery
interestingpieceofhistoricresearchaboutsomeofOaksbackwardscompatibilityhavingleakedintoJavato
thisdateinthisStackOverflowquestion(http://stackoverflow.com/a/7202659/521799).
WhileitwouldhavebeennaturaltodesignthereflectionAPIusingcollections,now,itwasalreadytoolate.
Abettersolutionmightvebeen:
ListgetConstructors()
However,notethatwedidnthavegenericsyet,sothearrayactuallyconveysmoretypeinformationthanthe
collection.
Java1.5:Generics
InJava5,thechangefrom
Constructor[]getConstructors()
to
Constructor<?>[]getConstructors()
hasbeenmadeforthereasonsmentionedabove.Now,thealternativeAPIusingacollectionwoulddefinitely
havebeenbetter:
List<Constructor<T>>getConstructors()

http://blog.jooq.org/category/java/

12/48

3/24/2015

java|Java,SQLandjOOQ.

Buttheshiphassailed.

Java,theuglywart
Javaisfulloftheselittlecaveats.TheyrealldocumentedintheJavadocs,andoftenonStackOverflow.Just
yesterday,wevedocumentedanewcaveatrelatedtocompletelynewAPIinMapandConcurrentHashMap
(http://blog.jooq.org/2015/03/04/avoidrecursioninconcurrenthashmapcomputeifabsent/).
Stewardship:theSoberingParts,averygoodtalkaboutallthosecaveatsandhowharditistomaintain
thembyBrianGoetzcanbeseenhere:

Thesummaryofthetalk:

(https://www.youtube.com/watch?
v=2y5Pv4yN0b0)
Whenlanguagedesignerstalkaboutthelanguagetheyredesigning
http://blog.jooq.org/category/java/

13/48

3/24/2015

java|Java,SQLandjOOQ.

March2,2015

injava,sql
Leaveacomment

jOOQEinalternativerWegmitJavaundSQL
zuarbeiten
WevepublishedanarticleintheGermanmagazinewww.javaaktuell.de(http://www.ijug.eu/java
aktuell/dasmagazin.html),whichispublishedbytheiJUGe.V.(http://www.ijug.eu/).
Youcanreadanddownloadthearticlefreeofchargefromourblog!
(https://lukaseder.files.wordpress.com/2015/03/022015javaaktuelllukasederjooqeinalternativerweg
mitjavaundsqlzuarbeiten.pdf)
InJavagibteskeinStandardAPI,dasdieAusdrucksstrkeundMchtigkeitvonSQLdirektuntersttzt.Alle
AufmerksamkeitistaufobjektrelationalesMappingundanderehhereAbstraktionslevelgerichtet,beispielsweise
OQL,HQL,JPQL,CriteriaQuery.jOOQisteinduallizenziertesOpenSourceProdukt,dasdieseLckefllt.Es
implementiertSQLalstypsicheredomnenspezifischeSprachedirektinJavaundisteineguteWahlfrJava
Applikationen,indenenSQLundherstellerspezifischeDatenbankfunktionalittwichtigsind.Eszeigt,wieeine
modernedomnenspezifischeSprachedieEntwicklerproduktivittstarkerhhenkann,indemSQLdirektinJava
eingebettetist.

http://blog.jooq.org/category/java/

14/48

3/24/2015

java|Java,SQLandjOOQ.

iJUGJavaAktuell[Februar2015]LukasEderjOOQeinalternativerWegmitJavaundSQLzuarbeiten
(https://www.slideshare.net/LukasEder1/ijugjavaaktuellfebruar2015lukasederjooqeinalternativer
wegmitjavaundsqlzuarbeiten)fromLukasEder(http://www.slideshare.net/LukasEder1)

February24,2015
injava,scala
Leaveacomment

jOOQvs.SlickProsandConsofEachApproach
Everyframeworkintroducesanewcompromise.Acompromisethatisintroducedbecausetheframework
makessomeassumptionsabouthowyoudliketointeractwithyoursoftwareinfrastructure.
AnexampleofwherethiscompromisehasstruckusersrecentlyisthediscussionAreSlickqueriesgenerally
isomorphictotheSQLqueries?(https://groups.google.com/d/msg/scalaquery/K2tch9yxx60/QB055F0pn3gJ).
And,ofcourse,theansweris:No.WhatappearstobeasimpleSlickquery:

http://blog.jooq.org/category/java/

15/48

3/24/2015

java|Java,SQLandjOOQ.

valsalesJoin=sales
joinpurchasers
joinproducts
joinsupplierson{
case(((sale,purchaser),product),supplier)=>
sale.productId===product.id&&
sale.purchaserId===purchaser.id&&
product.supplierId===supplier.id
}
turnsintoaratherlargemonsterwithtonsofderivedtablesthataretotallyunnecessary,giventheoriginal
query(formattingismine):
selectx2.x3,x4.x5,x2.x6,x2.x7
from(
selectx8.x9asx10,
x8.x11asx12,
x8.x13asx14,
x8.x15asx7,
x8.x16asx17,
x8.x18asx3,
x8.x19asx20,
x21.x22asx23,
x21.x24asx25,
x21.x26asx6
from(
selectx27.x28asx9,
x27.x29asx11,
x27.x30asx13,
x27.x31asx15,
x32.x33asx16,
x32.x34asx18,
x32.x35asx19
from(
selectx36."id"asx28,
x36."purchaser_id"asx29,
x36."product_id"asx30,
x36."total"asx31
from"sale"x36
)x27
innerjoin(
selectx37."id"asx33,
x37."name"asx34,
x37."address"asx35

from"purchaser"x37
)x32
on1=1
)x8
innerjoin(
http://blog.jooq.org/category/java/

16/48

3/24/2015

java|Java,SQLandjOOQ.

selectx38."id"asx22,
x38."supplier_id"asx24,
x38."name"asx26
from"product"x38
)x21
on1=1
)x2
innerjoin(
selectx39."id"asx40,
x39."name"asx5,
x39."address"asx41
from"supplier"x39
)x4
on((x2.x14=x2.x23)
and(x2.x12=x2.x17))
and(x2.x25=x4.x40)
wherex2.x7>=?
ChristopherVogt,aformerSlickmaintainerandstillactivelyinvolvedmemberoftheSlickcommunity,
explainstheaboveinthefollowingwords:
ThismeansthatSlickreliesonyourdatabasesqueryoptimizertobeabletoexecutethesqlquerythatSlick
producedefficiently.CurrentlythatisnotalwaysthecaseinMySQL
OneofthemainideasbehindSlick,accordingtoChristopher,is:
SlickisnotaDSLthatallowsyoutobuildexactlyspecifiedSQLstrings.SlicksScalaquerytranslationallowsfor
reuseandcompositionandusingScalaasthelanguagetowriteyourqueries.Itdoesnotallowyoutopredictthe
exactsqlquery,onlythesemanticsandtheroughstructure.

Slickvs.jOOQ
SinceChristopherlateronalsocomparedSlickwithjOOQ,Iallowedmyselftochimeinandtoaddmytwo
cents:

http://blog.jooq.org/category/java/
Fromahighlevel(withoutactualSlickexperience)IdsaythatSlickandjOOQembracecompositionalityequally17/48

3/24/2015

java|Java,SQLandjOOQ.

Fromahighlevel(withoutactualSlickexperience)IdsaythatSlickandjOOQembracecompositionalityequally
well.Iveseencrazyqueriesofseveral100soflinesof[jOOQ]SQLincustomercode,composedoverseveral
methods.YoucandothatwithbothAPIs.
Ontheotherhand,asChrissaid:SlickhasafocusonScalacollections,jOOQonSQLtables.
Fromaconceptualperspective(=intheory),thisfocusshouldntmatter.
Fromatypesafetyperspective,ScalacollectionsareeasiertotypecheckthanSQLtablesandqueriesbecause
SQLasalanguageitselfisratherhardtotypecheckgiventhatthesemanticsofvariousoftheadvancedSQL
clausesaltertypeconfigurationsratherimplicitly(e.g.outerjoins,groupingsets,pivotclauses,unions,group
by,etc.).
Fromapracticalperspective,SQLitselfisonlyanapproximationoftheoriginalrelationaltheoriesandhas
attainedalifeofitsown.Thismayormaynotmattertoyou.
IguessintheenditreallyboilsdowntowhetheryouwanttoreasonaboutScalacollections(queriesare
betterintegrated/moreidiomaticwithyourclientcode)oraboutSQLtables(queriesarebetter
integrated/moreidiomaticwithyourdatabase).
Atthispoint,Idliketoaddanothertwocentstothediscussion.Customersdontbuytheproductthatyoure
selling.Theyneverdo.InthecaseofHibernate,customersanduserswerehopingtobeabletoforgetSQL
forever.Theoppositeistrue.AsGavinKinghimself(thecreatorofHibernate)hadtoldme:

(https://plus.google.com/+GavinKing/posts/LGJU1NorAvY)
BecausecustomersandusershadneverlistenedtoGavin(andtootherORMcreators),wenowhavewhat
manycalltheobjectrelationalimpedancemismatch(https://en.wikipedia.org/wiki/Object
relational_impedance_mismatch).AlotofunjustifiedcriticismhasbeenexpressedagainstHibernateand
JPA,APIswhicharesimplytoopopularforthelimitedscopetheyreallycover.
WithSlick(orC#sLINQ,forthatmatter(http://blog.jooq.org/2013/11/02/doesjava8stillneedlinqorisit
betterthanlinq/)),asimilarmismatchisimpedingintegrations,ifusersabusethesetoolsforwhatthey
believetobeareplacementforSQL.Slickdoesagreatjobatmodellingtherelationalmodeldirectlyinthe
Scalalanguage.Thisiswonderfulifyouwanttoreasonaboutrelationsjustlikeyoureasonaboutcollections.
ButitisnotaSQLAPI.Toillustratehowdifficultitistoovercometheselimitations,youcanbrowsetheissue
trackerorusergrouptolearnabout:
Unwantedderivedtables(https://github.com/slick/slick/issues/623)
Limitedsupportforouterjoin(https://groups.google.com/forum/#!topic/scalaquery/Uv9C0QPhYFI)
Wellsimplycallthis:
TheFunctionalRelationalImpedanceMismatch

SQLismuchmore
http://blog.jooq.org/category/java/

18/48

3/24/2015

java|Java,SQLandjOOQ.

MarkusWinand(theauthorofthepopularSQLPerformanceExplained(http://sqlperformance
explained.com/l))hasrecentlypublishedaverygoodpresentationaboutmodernSQL,anideathatwe
fullyembraceatjOOQ:

ModernSQLinPostgreSQL(https://www.slideshare.net/MarkusWinand/modernsql)fromMarkus
Winand(http://www.slideshare.net/MarkusWinand)
WebelievethatAPIsthathavebeentryingtohidetheSQLlanguagefromgeneralpurposelanguageslike
Java,Scala,C#aremissingoutonalotoftheverynicefeaturesthatcanaddtremendousvaluetoyour
application.jOOQisanAPIthatfullyembracestheSQLlanguage,withallitsawesomefeatures(andwithall
itsquirks).Youobviouslymayormaynotagreewiththat.
Wellleavethisarticleopenended,hopingyoullchimeintodiscussthebenefitsandcaveatsofeach
approach.OfstayingclosetoScalavs.stayingclosetoSQL.
Asasmallteaser,however,Idliketoannounceafollowuparticleshowingthatthereisnosuchthingasan
objectrelationalimpedancemismatch.You(andyourORM)arejustnotusingSQLcorrectly.Staytuned!

February18,2015
injava
Leaveacomment

ThouShaltNotNameThyMethodEquals
(unlessyoureallyoverrideObject.equals()
(http://docs.oracle.com/javase/8/docs/api/java/lang/Object.html#equalsjava.lang.Object),ofcourse).
http://blog.jooq.org/category/java/
19/48
IvestumbleduponarathercuriousStackOverflowquestion(http://stackoverflow.com/q/28563304/521799)

3/24/2015

java|Java,SQLandjOOQ.

IvestumbleduponarathercuriousStackOverflowquestion(http://stackoverflow.com/q/28563304/521799)
byuserFrank:
WhydoesJavasArea#equalsmethodnotoverrideObject#equals?
Interestingly,thereisaArea.equals(Area)
(http://docs.oracle.com/javase/8/docs/api/java/awt/geom/Area.html#equalsjava.awt.geom.Area)method
whichreallytakesanAreaargument,insteadofaObjectargumentasdeclaredinObject.equals().This
leadstorathernastybehaviour,asdiscoveredbyFrank:
@org.junit.Test
publicvoidtestEquals(){
java.awt.geom.Areaa=newjava.awt.geom.Area();
java.awt.geom.Areab=newjava.awt.geom.Area();
assertTrue(a.equals(b));//>true
java.lang.Objecto=b;
assertTrue(a.equals(o));//>false
}
Technically,itiscorrectforAWTsAreatohavebeenimplementedthisway(ashashCode()isnt
implementedeither),butthewayJavaresolvesmethods,andthewayprogrammersdigestcodethathas
beenwrittenliketheabovecode,itisreallyaterribleideatooverloadtheequalsmethod.

Nostaticequals,either
Theserulesalsoholdtrueforstaticequals()methods,suchasforinstanceApacheCommonsLang
(http://commons.apache.org/proper/commonslang/)s
ObjectUtils.equals(Objecto1,Objecto2)
Theconfusionherearisesbythefactthatyoucannotstaticimportthisequalsmethod:
importstaticorg.apache.commons.lang.ObjectUtils.equals;
Whenyounowtypethefollowing:
equals(obj1,obj2);
Youwillgetacompilererror:
Themethodequals(Object)inthetypeObjectisnotapplicableforthearguments(,)
http://blog.jooq.org/category/java/

20/48

3/24/2015

java|Java,SQLandjOOQ.

Thereasonforthisisthatmethodsthatareinthescopeofthecurrentclassanditssupertypeswillalways
shadowanythingthatyouimportthisway.Thefollowingdoesntworkeither:
importstaticorg.apache.commons.lang.ObjectUtils.defaultIfNull;
publicclassTest{
voidtest(){
defaultIfNull(null,null);
//^^compilationerrorhere
}
voiddefaultIfNull(){
}
}
DetailsinthisStackOverflowquestion(http://stackoverflow.com/q/7890853/521799).

Conclusion
Theconclusionissimple.neveroverloadanyofthemethodsdeclaredinObject(overridingisfine,of
course).Thisincludes:
clone()
equals()
finalize()
getClass()
hashCode()
notify()
notifyAll()
toString()
wait()
Ofcourse,itwouldbegreatifthosemethodswerentdeclaredinObjectinthefirstplace,butthatshiphas
sailed20yearsago.

February5,2015
injava,java8
8Comments

Top10EasyPerformanceOptimisationsinJava
http://blog.jooq.org/category/java/

21/48

3/24/2015

java|Java,SQLandjOOQ.

Therehasbeenalotofhypeaboutthebuzzwordwebscale(http://www.mongodbiswebscale.com/),and
peoplearegoingthroughlengthsofreorganisingtheirapplicationarchitecturetogettheirsystemstoscale.
Butwhatisscaling,andhowcanwemakesurethatwecanscale?

Differentaspectsofscaling
Thehypementionedaboveismostlyaboutscalingload,i.e.tomakesurethatasystemthatworksfor1user
willalsoworkwellfor10users,or100users,ormillions.Ideally,yoursystemisasstatelessaspossible
suchthatthefewpiecesofstatethatreallyremaincanbetransferredandtransformedonanyprocessingunit
inyournetwork.Whenloadisyourproblem,latencyisprobablynot,soitsOKifindividualrequeststake
50100ms.Thisisoftenalsoreferredtoasscalingout
Anentirelydifferentaspectofscalingisaboutscalingperformance,i.e.tomakesurethatanalgorithmthat
worksfor1pieceofinformationwillalsoworkwellfor10pieces,or100pieces,ormillions.Whetherthis
typeofscalingisfeasibleisbestdescribedbyBigONotation(http://en.wikipedia.org/wiki/Big_O_notation).
Latencyisthekillerwhenscalingperformance.Youwanttodoeverythingpossibletokeepallcalculationon
asinglemachine.Thisisoftenalsoreferredtoasscalingup
Iftherewasanythinglikefreelunch(thereisnt(https://en.wikipedia.org/wiki/CAP_theorem)),wecould
indefinitelycombinescalingupandout.Anyway,today,weregoingtolookatsomeveryeasywaysto
improvethingsontheperformanceside.

BigONotation
Java7sForkJoinPool(http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ForkJoinPool.html)as
wellasJava8sparallelStream(docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html)help
parallelisingstuff,whichisgreatwhenyoudeployyourJavaprogramontoamulticoreprocessormachine.
Theadvantageofsuchparallelismcomparedtoscalingacrossdifferentmachinesonyournetworkisthefact
thatyoucanalmostcompletelyeliminatelatencyeffects,asallcorescanaccessthesamememory.
Butdontbefooledbytheeffectthatparallelismhas!Rememberthefollowingtwothings:
Parallelismeatsupyourcores.Thisisgreatforbatchprocessing,butanightmareforasynchronous
servers(suchasHTTP).Therearegoodreasonswhyweveusedthesinglethreadservletmodelinthe
pastdecades.Soparallelismonlyhelpswhenscalingup.
ParallelismhasnoeffectonyouralgorithmsBigONotation.IfyouralgorithmisO(nlogn),andyoulet
thatalgorithmrunonccores,youwillstillhaveanO(nlogn/c)algorithm,ascisaninsignificant
constantinyouralgorithmscomplexity.Youwillsavewallclocktime,butnotreducecomplexity!
Thebestwaytoimproveperformance,ofcourse,isbyreducingalgorithmcomplexity.Thekillerisachieve
O(1)orquasiO(1),ofcourse,forinstanceaHashMaplookup.Butthatisnotalwayspossible,letaloneeasy.

http://blog.jooq.org/category/java/
Ifyoucannotreduceyourcomplexity,youcanstillgainalotofperformanceifyoutweakyouralgorithm 22/48

3/24/2015

java|Java,SQLandjOOQ.

Ifyoucannotreduceyourcomplexity,youcanstillgainalotofperformanceifyoutweakyouralgorithm
whereitreallymatters,ifyoucanfindtherightspots.Assumethefollowingvisualrepresentationofan
algorithm:

(https://lukaseder.files.wordpress.com/2015/02/algorithm2.png)
TheoverallcomplexityofthealgorithmisO(N3),orO(NxOxP)ifwewanttodealwithindividualorders
ofmagnitude.However,whenprofilingthiscode,youmightfindafunnyscenario:
Onyourdevelopmentbox,theleftbranch(N>M>Heavyoperation)istheonlybranchthatyou
canseeinyourprofiler,becausethevaluesforOandParesmallinyourdevelopmentsampledata.
Onproduction,however,therightbranch(N>O>P>EasyoperationoralsoN.O.P.E.)isreally
causingtrouble.YouroperationsteammighthavefiguredthisoutusingAppDynamics
(http://www.appdynamics.com),orDynaTrace(http://www.dynatrace.com),orsomesimilarsoftware.
Withoutproductiondata,youmightquicklyjumptoconclusionsandoptimisetheheavyoperation.You
shiptoproductionandyourfixhasnoeffect.
Therearenogoldenrulestooptimisationapartfromthefactsthat:
Awelldesignedapplicationismucheasiertooptimise
Prematureoptimisationwillnotsolveanyperformanceproblems,butmakeyourapplicationlesswell
designed,whichinturnmakesithardertobeoptimised
Enoughtheory.Letsassumethatyouhavefoundtherightbranchtobetheissue.Itmaywellbethatavery
easyoperationisblowingupinproduction,becauseitiscalledlotsandlotsoftimes(ifN,O,andParelarge).
PleasereadthisarticleinthecontextoftherebeingaproblemattheleafnodeofaninevitableO(N3)
algorithm.Theseoptimisationswonthelpyouscale.Theyllhelpyousaveyourcustomersdayfornow,
deferringthedifficultimprovementoftheoverallalgorithmuntillater!
Herearethetop10easyperformanceoptimisationsinJava:

http://blog.jooq.org/category/java/

23/48

3/24/2015

java|Java,SQLandjOOQ.

1.UseStringBuilder
ThisshouldbeyourdefaultinalmostallJavacode.Trytoavoidthe+operator.Sure,youmayarguethatitis
justsyntaxsugarforaStringBuilder
(http://docs.oracle.com/javase/8/docs/api/java/lang/StringBuilder.html)anyway,asin:
Stringx="a"+args.length+"b";
whichcompilesto

0newjava.lang.StringBuilder[16]
3dup
4ldc<String"a">[18]
6invokespecialjava.lang.StringBuilder(java.lang.String)[20]
9aload_0[args]
10arraylength
11invokevirtualjava.lang.StringBuilder.append(int):java.lang.StringBuilder[23]
14ldc<String"b">[27]
16invokevirtualjava.lang.StringBuilder.append(java.lang.String):java.lang.StringBuild
19invokevirtualjava.lang.StringBuilder.toString():java.lang.String[32]
22astore_1[x]

Butwhathappens,iflateron,youneedtoamendyourStringwithoptionalparts?
Stringx="a"+args.length+"b";
if(args.length==1)
x=x+args[0];
YouwillnowhaveasecondStringBuilder,thatjustneedlesslyconsumesmemoryoffyourheap,putting
pressureonyourGC.Writethisinstead:
StringBuilderx=newStringBuilder("a");
x.append(args.length);
x.append("b");
if(args.length==1);
x.append(args[0]);
Takeaway
http://blog.jooq.org/category/java/

24/48

3/24/2015

java|Java,SQLandjOOQ.

Intheaboveexample,itisprobablycompletelyirrelevantifyoureusingexplicitStringBuilderinstances,
orifyourelyontheJavacompilercreatingimplicitinstancesforyou.Butremember,wereintheN.O.P.E.
branch.EveryCPUcyclethatwerewastingonsomethingasstupidasGCorallocatingaStringBuilders
defaultcapacity,werewastingNxOxPtimes.
Asaruleofthumb,alwaysuseaStringBuilder
(http://docs.oracle.com/javase/8/docs/api/java/lang/StringBuilder.html)ratherthanthe+operator.Andifyou
can,keeptheStringBuilderreferenceacrossseveralmethods,ifyourStringismorecomplextobuild.
ThisiswhatjOOQ(http://www.jooq.org)doeswhenyougenerateacomplexSQLstatement.Thereisonly
oneStringBuilderthattraversesyourwholeSQLAST(AbstractSyntaxTree)
(http://en.wikipedia.org/wiki/Abstract_syntax_tree)
Andforcryingoutloud,ifyoustillhaveStringBuffer
(http://docs.oracle.com/javase/8/docs/api/java/lang/StringBuffer.html)references,doreplacethemby
StringBuilder.Youreallyhardlyeverneedtosynchronizeonastringbeingcreated.

2.Avoidregularexpressions
Regularexpressionsarerelativelycheapandconvenient.ButifyoureintheN.O.P.E.branch,theyreaboutthe
worstthingyoucando.Ifyouabsolutelymustuseregularexpressionsincomputationintensivecode
sections,atleastcachethePattern(http://docs.oracle.com/javase/8/docs/api/java/util/regex/Pattern.html)
referenceinsteadofcompilingitafreshallthetime:
staticfinalPatternHEAVY_REGEX=
Pattern.compile("(((X)*Y)*Z)*");
Butifyourregularexpressionisreallysillylike
String[]parts=ipAddress.split("\\.");
thenyoureallybetterresorttoordinarychar[]orindexbasedmanipulation.Forexamplethisutterly
unreadableloopdoesthesamething:

http://blog.jooq.org/category/java/

25/48

3/24/2015

java|Java,SQLandjOOQ.

intlength=ipAddress.length();
intoffset=0;
intpart=0;
for(inti=0;i<length;i++){
if(i==length1||
ipAddress.charAt(i+1)=='.'){
parts[part]=
ipAddress.substring(offset,i+1);
part++;
offset=i+2;
}
}
whichalsoshowswhyyoushouldntdoanyprematureoptimisation.Comparedtothesplit()version,
thisisunmaintainable.
Challenge:Thecleveronesamongyourreadersmightfindevenfasteralgorithms.
Takeaway
Regularexpressionsareuseful,buttheycomeataprice.IfyouredeepdowninaN.O.P.E.branch,youmust
avoidregularexpressionsatallcosts.BewareofavarietyofJDKStringmethods,thatuseregular
expressions,suchasString.replaceAll()
(http://docs.oracle.com/javase/8/docs/api/java/lang/String.html#replaceAlljava.lang.Stringjava.lang.String),
orString.split()(http://docs.oracle.com/javase/8/docs/api/java/lang/String.html#splitjava.lang.String).
UseapopularlibrarylikeApacheCommonsLang(http://commons.apache.org/proper/commonslang/)
instead,foryourStringmanipulation.

3.Donotuseiterator()
Now,thisadviceisreallynotforgeneralusecases,butonlyapplicabledeepdowninaN.O.P.E.branch.
Nonetheless,youshouldthinkaboutit.WritingJava5styleforeachloopsisconvenient.Youcanjust
completelyforgetaboutloopinginternals,andwrite:
for(Stringvalue:strings){
//Dosomethingusefulhere
}
However,everytimeyourunintothisloop,ifstringsisanIterable
(https://docs.oracle.com/javase/8/docs/api/java/lang/Iterable.html),youwillcreateanewIterator
(https://docs.oracle.com/javase/8/docs/api/java/util/Iterator.html)instance.IfyoureusinganArrayList
(https://docs.oracle.com/javase/8/docs/api/java/util/ArrayList.html),thisisgoingtobeallocatinganobject
with3intsonyourheap:
http://blog.jooq.org/category/java/

26/48

3/24/2015

java|Java,SQLandjOOQ.

privateclassItrimplementsIterator<E>{
intcursor;
intlastRet=1;
intexpectedModCount=modCount;
//...
Instead,youcanwritethefollowing,equivalentloopandwasteonlyasingleintvalueonthestack,which
isdirtcheap:
intsize=strings.size();
for(inti=0;i<size;i++){
Stringvalue:strings.get(i);
//Dosomethingusefulhere
}
or,ifyourlistdoesntreallychange,youmightevenoperateonanarrayversionofit:
for(Stringvalue:stringArray){
//Dosomethingusefulhere
}
Takeaway
Iterators,Iterable,andtheforeachloopareextremelyusefulfromawriteabilityandreadabilityperspective,
aswellasfromanAPIdesignperspective.However,theycreateasmallnewinstanceontheheapforeach
singleiteration.Ifyourunthisiterationmanymanytimes,youwanttomakesuretoavoidcreatingthis
uselessinstance,andwriteindexbasediterationsinstead.
Discussion
Someinterestingdisagreementaboutpartsoftheabove(inparticularreplacingIteratorusagebyaccess
byindex)hasbeendiscussedonReddithere
(http://www.reddit.com/r/java/comments/2uuzv1/top_10_easy_performance_optimisations_in_java/cobzlng).

4.Dontcallthatmethod
Somemethodsaresimpleexpensive.InourN.O.P.E.branchexample,wedonthavesuchamethodatthe
leaf,butyoumaywellhaveone.LetsassumeyourJDBCdriverneedstogothroughincredibletroubleto
calculatethevalueofResultSet.wasNull()
(http://docs.oracle.com/javase/8/docs/api/java/sql/ResultSet.html#wasNull).YourhomegrownSQL
frameworkcodemightlooklikethis:

http://blog.jooq.org/category/java/

27/48

3/24/2015

java|Java,SQLandjOOQ.

if(type==Integer.class){
result=(T)wasNull(rs,
Integer.valueOf(rs.getInt(index)));
}
//Andthen...
staticfinal<T>TwasNull(ResultSetrs,Tvalue)
throwsSQLException{
returnrs.wasNull()?null:value;
}
ThislogicwillnowcallResultSet.wasNull()everytimeyougetanintfromtheresultset.Butthe
getInt()contractreads:
Returns:thecolumnvalue;ifthevalueisSQLNULL,thevaluereturnedis0
Thus,asimple,yetpossiblydrasticimprovementtotheabovewouldbe:
staticfinal<TextendsNumber>TwasNull(
ResultSetrs,Tvalue
)
throwsSQLException{
return(value==null||
(value.intValue()==0&&rs.wasNull()))
?null:value;
}
So,thisisanobrainer:
Takeaway
Dontcallexpensivemethodsinanalgorithmsleafnodes,butcachethecallinstead,oravoiditifthe
methodcontractallowsit.

5.Useprimitivesandthestack
TheaboveexampleisfromjOOQ(http://www.jooq.org),whichusesalotofgenerics,andthusisforcedto
usewrappertypesforbyte,short,int,andlongatleastbeforegenericswillbespecialisableinJava10
andprojectValhalla(http://cr.openjdk.java.net/~briangoetz/valhalla/specialization.html).Butyoumaynot
havethisconstraintinyourcode,soyoushouldtakeallmeasurestoreplace:
//Goestotheheap
Integeri=817598;

http://blog.jooq.org/category/java/

28/48

3/24/2015

java|Java,SQLandjOOQ.

bythis:
//Staysonthestack
inti=817598;
Thingsgetworsewhenyoureusingarrays:
//Threeheapobjects!
Integer[]i={1337,424242};
bythis:
//Oneheapobject.
int[]i={1337,424242};
Takeaway
WhenyouredeepdowninyourN.O.P.E.branch,youshouldbeextremelywaryofusingwrappertypes.
ChancesarethatyouwillcreatealotofpressureonyourGC,whichhastokickinallthetimetocleanup
yourmess.
Aparticularlyusefuloptimisationmightbetousesomeprimitivetypeandcreatelarge,onedimensional
arraysofit,andacoupleofdelimitervariablestoindicatewhereexactlyyourencodedobjectislocatedon
thearray.
Anexcellentlibraryforprimitivecollections,whichareabitmoresophisticatedthanyouraverageint[]is
trove4j(http://trove4j.sourceforge.net),whichshipswithLGPL.
Exception
Thereisanexceptiontothisrule:booleanandbytehavefewenoughvaluestobecachedentirelybythe
JDK.Youcanwrite:
Booleana1=true;//...syntaxsugarfor:
Booleana2=Boolean.valueOf(true);
Byteb1=(byte)123;//...syntaxsugarfor:
Byteb2=Byte.valueOf((byte)123);
Thesameistrueforlowvaluesoftheotherintegerprimitivetypes,includingchar,short,int,long.
Butonlyifyoureautoboxingthem,orcallingTheType.valueOf(),notwhenyoucalltheconstructor!
Nevercalltheconstructoronwrappertypes,unlessyoureallywantanewinstance
Thisfactcanalsohelpyouwriteasophisticated,trollingAprilFoolsjokeforyourcoworkers
(http://blog.jooq.org/2013/10/17/addsomeentropytoyourjvm/)
http://blog.jooq.org/category/java/

29/48

3/24/2015

java|Java,SQLandjOOQ.

Offheap
Ofcourse,youmightalsowanttoexperimentwithoffheaplibraries,althoughtheyremoreofastrategic
decision,notalocaloptimisation.
AninterestingarticleonthatsubjectbyPeterLawreyandBenCottonis:OpenJDKandHashMapSafely
TeachinganOldDogNew(OffHeap!)Tricks(http://www.infoq.com/articles/OpenJDKandHashMapOff
Heap)

6.Avoidrecursion
ModernfunctionalprogramminglanguageslikeScalaencouragetheuseofrecursion,astheyoffermeansof
optimisingtailrecursingalgorithmsbackintoiterativeones(http://stackoverflow.com/q/33923/521799).If
yourlanguagesupportssuchoptimisations,youmightbefine.Buteventhen,theslightestchangeof
algorithmmightproduceabranchthatpreventsyourrecursionfrombeingtailrecursive.Hopefullythe
compilerwilldetectthis!Otherwise,youmightbewastingalotofstackframesforsomethingthatmight
havebeenimplementedusingonlyafewlocalvariables.
Takeaway
Theresnotmuchtosayaboutthisapartfrom:Alwayspreferiterationoverrecursionwhenyouredeep
downtheN.O.P.E.branch

7.UseentrySet()
WhenyouwanttoiteratethroughaMap(https://docs.oracle.com/javase/8/docs/api/java/util/Map.html),and
youneedbothkeysandvalues,youmusthaveaverygoodreasontowritethefollowing:
for(Kkey:map.keySet()){
Vvalue:map.get(key);
}
ratherthanthefollowing:
for(Entry<K,V>entry:map.entrySet()){
Kkey=entry.getKey();
Vvalue=entry.getValue();
}

http://blog.jooq.org/category/java/
30/48
WhenyoureintheN.O.P.E.branch,youshouldbewaryofmapsanyway,becauselotsandlotsofO(1)map

3/24/2015

java|Java,SQLandjOOQ.

WhenyoureintheN.O.P.E.branch,youshouldbewaryofmapsanyway,becauselotsandlotsofO(1)map
accessoperationsarestilllotsofoperations.Andtheaccessisntfreeeither.Butatleast,ifyoucannotdo
withoutmaps,useentrySet()(https://docs.oracle.com/javase/8/docs/api/java/util/Map.html#entrySet)to
iteratethem!TheMap.Entryinstanceisthereanyway,youonlyneedtoaccessit.
Takeaway
AlwaysuseentrySet()whenyouneedbothkeysandvaluesduringmapiteration.

8.UseEnumSetorEnumMap
Therearesomecaseswherethenumberofpossiblekeysinamapisknowninadvanceforinstancewhen
usingaconfigurationmap.Ifthatnumberisrelativelysmall,youshouldreallyconsiderusingEnumSetor
EnumMap,insteadofregularHashSetorHashMapinstead.Thisiseasilyexplainedbylookingat
EnumMap.put():
privatetransientObject[]vals;
publicVput(Kkey,Vvalue){
//...
intindex=key.ordinal();
vals[index]=maskNull(value);
//...
}
Theessenceofthisimplementationisthefactthatwehaveanarrayofindexedvaluesratherthanahash
table.Wheninsertinganewvalue,allwehavetodotolookupthemapentryisasktheenumforitsconstant
ordinal,whichisgeneratedbytheJavacompileroneachenumtype.Ifthisisaglobalconfigurationmap(i.e.
onlyoneinstance),theincreasedaccessspeedwillhelpEnumMapheavilyoutperformHashMap,whichmay
useabitlessheapmemory,butwhichwillhavetorunhashCode()andequals()oneachkey.
Takeaway
EnumandEnumMapareveryclosefriends.Wheneveryouuseenumlikestructuresaskeys,consideractually
makingthosestructuresenumsandusingthemaskeysinEnumMap.

9.OptimiseyourhashCode()andequals()methods
IfyoucannotuseanEnumMap,atleastoptimiseyourhashCode()andequals()methods.Agood
hashCode()methodisessentialbecauseitwillpreventfurthercallstothemuchmoreexpensiveequals()
asitwillproducemoredistincthashbucketspersetofinstances.
http://blog.jooq.org/category/java/

31/48

3/24/2015

java|Java,SQLandjOOQ.

Ineveryclasshierarchy,youmayhavepopularandsimpleobjects.LetshavealookatjOOQs
org.jooq.Table(http://www.jooq.org/javadoc/latest/org/jooq/Table.html)implementations.
ThesimplestandfastestpossibleimplementationofhashCode()isthisone:
//AbstractTable,acommonTablebaseimplementation:
@Override
publicinthashCode(){
//[#1938]ThisisamuchmoreefficienthashCode()
//implementationcomparedtothatofstandard
//QueryParts
returnname.hashCode();
}
wherenameissimplythetablename.Wedontevenconsidertheschemaoranyotherpropertyofthe
table,asthetablenamesareusuallydistinctenoughacrossadatabase.Also,thenameisastring,soithas
alreadyacachedhashCode()valueinside.
Thecommentisimportant,becauseAbstractTableextendsAbstractQueryPart,whichisacommonbase
implementationforanyAST(AbstractSyntaxTree)(https://en.wikipedia.org/wiki/Abstract_syntax_tree)
element.ThecommonASTelementdoesnothaveanyproperties,soitcannotmakeanyassumptionsan
optimisedhashCode()implementation.Thus,theoverriddenmethodlookslikethis:
//AbstractQueryPart,acommonASTelement
//baseimplementation:
@Override
publicinthashCode(){
//Thisisaworkingdefaultimplementation.
//Itshouldbeoverriddenbyconcretesubclasses,
//toimproveperformance
returncreate().renderInlined(this).hashCode();
}
Inotherwords,thewholeSQLrenderingworkflowhastobetriggeredtocalculatethehashcodeofa
commonASTelement.
Thingsgetmoreinterestingwithequals()

http://blog.jooq.org/category/java/

32/48

3/24/2015

java|Java,SQLandjOOQ.

//AbstractTable,acommonTablebaseimplementation:
@Override
publicbooleanequals(Objectthat){
if(this==that){
returntrue;
}
//[#2144]Nonequalitycanbedecidedearly,
//withoutexecutingtheratherexpensive
//implementationofAbstractQueryPart.equals()
if(thatinstanceofAbstractTable){
if(StringUtils.equals(name,
(((AbstractTable<?>)that).name))){
returnsuper.equals(that);
}
returnfalse;
}
returnfalse;
}
Firstthing:Always(notonlyinaN.O.P.E.branch)aborteveryequals()methodearly,if:
this==argument
this"incompatibletype"argument
Notethatthelatterconditionincludesargument==null,ifyoureusinginstanceoftocheckfor
compatibletypes.Wevebloggedaboutthisbeforein10SubtleBestPracticeswhenCodingJava
(http://blog.jooq.org/2013/08/20/10subtlebestpracticeswhencodingjava/).
Now,afterabortingcomparisonearlyinobviouscases,youmightalsowanttoabortcomparisonearlywhen
youcanmakepartialdecisions.Forinstance,thecontractofjOOQsTable.equals()isthatfortwotablesto
beconsideredequal,theymustbeofthesamename,regardlessoftheconcreteimplementationtype.For
instance,thereisnowaythesetwoitemscanbeequal:
com.example.generated.Tables.MY_TABLE
DSL.tableByName("MY_OTHER_TABLE")
Iftheargumentcannotbeequaltothis,andifwecancheckthateasily,letsdosoandabortifthecheck
fails.Ifthechecksucceeds,wecanstillproceedwiththemoreexpensiveimplementationfromsuper.Given
thatmostobjectsintheuniversearenotequal,weregoingtosavealotofCPUtimebyshortcuttingthis
method.
someobjectsaremoreequalthanothers
InthecaseofjOOQ,mostinstancesarereallytablesasgeneratedbythejOOQsourcecodegenerator
(http://www.jooq.org/doc/3.5/manual/codegeneration/),whoseequals()implementationisevenfurther
optimised.Thedozensofothertabletypes(derivedtables,tablevaluedfunctions,arraytables,joinedtables,
http://blog.jooq.org/category/java/

33/48

3/24/2015

java|Java,SQLandjOOQ.

pivottables,commontableexpressions,etc.)cankeeptheirsimpleimplementation.

10.Thinkinsets,notinindividualelements
Lastbutnotleast,thereisathingthatisnotJavarelatedbutappliestoanylanguage.Besides,wereleaving
theN.O.P.E.branchasthisadvicemightjusthelpyoumovefromO(N3)toO(nlogn),orsomethinglike
that.
Unfortunately,manyprogrammersthinkintermsofsimple,localalgorithms.Theyresolvingaproblemstep
bystep,branchbybranch,loopbyloop,methodbymethod.Thatstheimperativeand/orfunctional
programmingstyle.Whileitisincreasinglyeasytomodelthebiggerpicturewhengoingfrompure
imperativetoobjectoriented(stillimperative)tofunctionalprogramming,allthesestyleslacksomething
thatonlySQLandRandsimilarlanguageshave:
Declarativeprogramming.
InSQL(andweloveit,asthisisthejOOQblog(http://blog.jooq.org))youcandeclaretheoutcomeyouwant
togetfromyourdatabase,withoutmakinganyalgorithmicimplicationswhatsoever.Thedatabasecanthen
takeallthemetadataavailableintoconsideration(e.g.constraints,keys,indexes,etc.
(http://blog.jooq.org/2011/11/25/howschemametadataimpactsoraclequerytransformations/))tofigureout
thebestpossiblealgorithm.
Intheory,thishasbeenthemainideabehindSQLandrelationalcalculus
(https://en.wikipedia.org/wiki/Relational_calculus)fromthebeginning.Inpractice,SQLvendorshave
implementedhighlyefficientCBOs(CostBasedOptimisers)(https://www.youtube.com/watch?
v=CjY8TCU69TU)onlysincethelastdecade,sostaywithusinthe2010swhenSQLwillfinallyunleashits
fullpotential(itwasabouttime!)
ButyoudonthavetodoSQLtothinkinsets.Sets/collections/bags/listsareavailableinalllanguagesand
libraries.Themainadvantageofusingsetsisthefactthatyouralgorithmswillbecomemuchmuchmore
concise.Itissomucheasiertowrite:
SomeSetINTERSECTSomeOtherSet
ratherthan:
//PreJava8
Setresult=newHashSet();
for(Objectcandidate:someSet)
if(someOtherSet.contains(candidate))
result.add(candidate);
//EvenJava8doesn'treallyhelp
someSet.stream()
.filter(someOtherSet::contains)
.collect(Collectors.toSet());
http://blog.jooq.org/category/java/

34/48

3/24/2015

java|Java,SQLandjOOQ.

SomemayarguethatfunctionalprogrammingandJava8willhelpyouwriteeasier,moreconcise
algorithms.Thatsnotnecessarilytrue.YoucantranslateyourimperativeJava7loopintoafunctionalJava8
Streamcollection,butyourestillwritingtheverysamealgorithm.WritingaSQLesqueexpressionis
different.This
SomeSetINTERSECTSomeOtherSet
canbeimplementedin1000waysbytheimplementationengine.Aswevelearnedtoday,perhapsitis
wisetotransformthetwosetsintoEnumSetautomatically,beforerunningtheINTERSECToperation.Perhaps
wecanparallelisethisINTERSECTwithoutmakinglowlevelcallstoStream.parallel()
(https://docs.oracle.com/javase/8/docs/api/java/util/stream/BaseStream.html#parallel)

Conclusion
Inthisarticle,wevetalkedaboutoptimisationsdoneontheN.O.P.E.branch,i.e.deepdowninahigh
complexityalgorithm.Inourcase,beingthejOOQ(http://www.jooq.org)developers,wehaveinterestin
optimisingourSQLgeneration:
EveryqueryisgeneratedonlyonasingleStringBuilder
Ourtemplatingengineactuallyparsescharacters,insteadofusingregularexpressions
Weusearrayswhereverwecan,especiallywheniteratingoverlisteners
WestayclearofJDBCmethodsthatwedonthavetocall
etc
jOOQisatthebottomofthefoodchain,becauseitsthe(second)lastAPIthatisbeingcalledbyour
customersapplicationsbeforethecallleavestheJVMtoentertheDBMS.Beingatthebottomofthefood
chainmeansthateverylineofcodethatisexecutedinjOOQmightbecalledNxOxPtimes,sowemust
optimiseeagerly.
YourbusinesslogicisnotdeepdownintheN.O.P.E.branch.Butyourown,homegrowninfrastructurelogic
maybe(customSQLframeworks,customlibraries,etc.)Thoseshouldbereviewedaccordingtotherulesthat
weveseentoday.Forinstance,usingJavaMissionControl(http://blog.jooq.org/2014/02/17/freejava
profilingwithoraclejavamissioncontrol/)oranyotherprofiler.
Likedthisarticle?
Ifyoucantgoandprofileyourapplicationrightnow,youmightenjoyreadinganyofthesearticlesinstead:
10SubtleMistakesWhenUsingtheStreamsAPI(http://blog.jooq.org/2014/06/13/java8friday10subtle
mistakeswhenusingthestreamsapi/)
10ThingsYouDidntKnowAboutJava(http://blog.jooq.org/2014/11/03/10thingsyoudidntknow
aboutjava/)
10SubtleBestPracticeswhenCodingJava(http://blog.jooq.org/2013/08/20/10subtlebestpracticeswhen
codingjava/)

February2,2015
injava

http://blog.jooq.org/category/java/

35/48

3/24/2015

java|Java,SQLandjOOQ.

4Comments

Top5UseCasesForNestedTypes
Therehasbeenaninterestingdiscussiononreddit,theotherdayStaticInnerClasses.Whenisittoomuch?
(http://redd.it/2u4512)
First,letsreviewalittlebitofbasichistoricJavaknowledge.Javathelanguageoffersfourlevelsofnesting
classes(http://docs.oracle.com/javase/tutorial/java/javaOO/nested.html),andbyJavathelanguage,Imean
thattheseconstructsaremeresyntaxsugar.TheydontexistintheJVM,whichonlyknowsordinary
classes.
(Static)Nestedclasses
classOuter{
staticclassInner{
}
}
Inthiscase,InneriscompletelyindependentofOuter,exceptforacommon,sharednamespace.
Innerclasses
classOuter{
classInner{
}
}
Inthiscase,InnerinstanceshaveanimplicitreferencetotheirenclosingOuterinstance.Inotherwords,
therecanbenoInnerinstancewithoutanassociatedOuterinstance.
TheJavawayofcreatingsuchaninstanceisthis:
Outer.Inneryikes=newOuter().newInner();
Whatlookstotallyawkwardmakesalotofsense.ThinkaboutcreatinganInnerinstancesomewhereinside
ofOuter:

http://blog.jooq.org/category/java/

36/48

3/24/2015

java|Java,SQLandjOOQ.

classOuter{
classInner{
}
voidsomewhereInside(){
//We'realreadyinthescopeofOuter.
//Wedon'thavetoqualifyInnerexplicitly.
InneraaahOK;
//Thisiswhatwe'reusedtowriting.
aaahOK=newInner();
//Asallotherlocallyscopedmethods,wecan
//accesstheInnerconstructorby
//dereferencingitfrom"this".Wejust
//hardlyeverwrite"this"
aaahOK=this.newInner();
}
}
Notethatmuchlikethepublicorabstractkeywords,thestatickeywordisimplicitfornestedinterfaces.
Whilethefollowinghypotheticalsyntaxmightlookfamiliaratfirstsight:
classOuter{
<nonstatic>interfaceInner{
defaultvoiddoSomething(){
Outer.this.doSomething();
}
}
voiddoSomething(){}
}
itisnotpossibletowritetheabove.Apartfromthelackofa<nonstatic>keyword,theredontseemto
beanyobviousreasonwhyinnerinterfacesshouldntbepossible.Idsuspecttheusualtheremustbe
somereallyedgecaseycaveatrelatedtobackwardscompatibilityand/ormultipleinheritancethatprevents
this.
Localclasses
classOuter{
voidsomewhereInside(){
classInner{
}
}
}

http://blog.jooq.org/category/java/

37/48

3/24/2015

java|Java,SQLandjOOQ.

LocalclassesareprobablyoneoftheleastknownfeaturesinJava,asthereishardlyanyuseforthem.Local
classesarenamedtypeswhosescopeextendsonlytotheenclosingmethod.Obvioususecasesarewhenyou
wanttoreusesuchatypeseveraltimeswithinthatmethod,e.g.toconstructseveralsimilarlistenersina
JavaFXapplication.
Anonymousclasses
classOuter{
Serializabledummy=newSerializable(){};
}
Anonymousclassesaresubtypesofanothertypewithonlyonesingleinstance.

Top5UseCasesForNestedClasses
Allofanonymous,local,andinnerclasseskeepareferencetotheirenclosinginstance,iftheyrenotdefined
inastaticcontext.Thismaycausealotoftroubleifyouletinstancesoftheseclassesleakoutsideoftheir
scope.Readmoreaboutthattroubleinourarticle:DontbeClever:TheDoubleCurlyBracesAntiPattern
(http://blog.jooq.org/2014/12/08/dontbecleverthedoublecurlybracesantipattern/).
Often,however,youdowanttoprofitfromthatenclosinginstance.Itcanbequiteusefultohavesomesortof
messageobjectthatyoucanreturnwithoutdisclosingtheactualimplementation:
classOuter{
//Thisimplementationisprivate...
privateclassInnerimplementsMessage{
@Override
publicvoidgetMessage(){
Outer.this.someoneCalledMe();
}
}
//...butwecanreturnit,beingof
//typeMessage
Messagehello(){
returnnewInner();
}
voidsomeoneCalledMe(){}
}
With(static)nestedclasses,however,thereisnoenclosingscopeastheInnerinstanceiscompletely
independentofanyOuterinstance.Sowhatsthepointofusingsuchanestedclass,ratherthanatoplevel
type?
http://blog.jooq.org/category/java/

38/48

3/24/2015

java|Java,SQLandjOOQ.

1.Associationwiththeoutertype
Ifyouwanttocommunicatetothewholeworld,hey,this(inner)typeistotallyrelatedtothis(outer)type,
anddoesntmakesenseonitsown,thenyoucannestthetypes.ThishasbeendonewithMapand
Map.Entry,forinstance:
publicinterfaceMap<K,V>{
interfaceEntry<K,V>{
}
}

2.Hidingfromtheoutsideoftheoutertype
Ifpackage(default)visibilityisntenoughforyourtypesyoucancreateprivatestaticclassesthatare
availableonlytotheirenclosingtypeandtoallothernestedtypesoftheenclosingtype.Thisisreallythe
mainusecaseforstaticnestedclasses.
classOuter{
privatestaticclassInner{
}
}
classOuter2{
Outer.Innernope;
}

3.Protectedtypes
Thisisreallyaveryrareusecase,butsometimes,withinaclasshierarchy,youneedtypesthatyouwantto
makeavailableonlytosubtypesofagiventype.Thisisausecaseforprotectedstaticclasses:

http://blog.jooq.org/category/java/

39/48

3/24/2015

java|Java,SQLandjOOQ.

classParent{
protectedstaticclassOnlySubtypesCanSeeMe{
}
protectedOnlySubtypesCanSeeMesomeMethod(){
returnnewOnlySubtypesCanSeeMe();
}
}
classChildextendsParent{
OnlySubtypesCanSeeMewow=someMethod();
}

4.Toemulatemodules
UnlikeCeylon,Javadoesnthavefirstclassmodules(http://blog.jooq.org/2013/12/03/top10ceylonlanguage
featuresiwishwehadinjava/).WithMavenorOSGi,itispossibletoaddsomemodularbehaviourto
Javasbuild(Maven)orruntime(OSGi)environments,butifyouwanttoexpressmodulesincode,thisisnt
reallypossible.
However,youcanestablishmodulesbyconventionbyusingstaticnestedclasses.Letslookatthe
java.util.stream(http://docs.oracle.com/javase/8/docs/api/java/util/stream/package
summary.html)package.Wecouldconsideritamodule,andwithinthismodule,wehaveacoupleofsub
modules,orgroupsoftypes,suchastheinternaljava.util.stream.Nodesclass,whichroughlylookslike
this:
finalclassNodes{
privateNodes(){}
privatestaticabstractclassAbstractConcNode{}
staticfinalclassConcNode{
staticfinalclassOfInt{}
staticfinalclassOfLong{}
}
privatestaticfinalclassFixedNodeBuilder{}
//...
}
SomeofthisNodesstuffisavailabletoallofthejava.util.streampackage,sowemightsaythattheway
thisiswritten,wehavesomethinglike:
asyntheticjava.util.stream.nodessubpackage,visibleonlytothejava.util.streammodule
acoupleofjava.util.stream.nodes.*types,visiblealsoonlytothejava.util.streammodule
acoupleoftoplevelfunctions(staticmethods)inthesyntheticjava.util.stream.nodespackage
http://blog.jooq.org/category/java/

40/48

3/24/2015

java|Java,SQLandjOOQ.

LooksalotlikeCeylon,tome!(http://blog.jooq.org/2013/12/03/top10ceylonlanguagefeaturesiwishwe
hadinjava/)

5.Cosmeticreasons
Thelastbitisratherboring.Orsomemayfinditinteresting(http://blog.jooq.org/2014/07/25/top10very
veryveryimportanttopicstodiscuss/).Itsabouttaste,oreaseofwritingthings.Someclassesarejustso
smallandunimportant,itsjusteasiertowritetheminsideofanotherclass.Savesyoua.javafile.Whynot.

Conclusion
IntimesofJava8,thinkingabouttheveryoldfeaturesofJavathelanguagemightnotprovetobeextremely
exciting.Staticnestedclassesareawellunderstoodtoolforacoupleofnicheusecases.
Thetakeawayfromthisarticle,however,isthis.Everytimeyounestaclass,besuretomakeitstaticifyou
dontabsolutelyneedareferencetotheenclosinginstance.Youneverknowwhenthatreferenceisblowing
upyourapplicationinproduction(http://blog.jooq.org/2014/12/08/dontbecleverthedoublecurlybraces
antipattern/).

January29,2015
injava,java8
4Comments

YouWillRegretApplyingOverloadingwithLambdas!
WritinggoodAPIsishard.Extremelyhard.Youhavetothinkofanincredibleamountofthingsifyouwant
youruserstoloveyourAPI.Youhavetofindtherightbalancebetween:
1.
2.
3.
4.

Usefulness
Usability
Backwardcompatibility
Forwardcompatibility

Wevebloggedaboutthistopicbefore,inourarticle:HowtoDesignaGood,RegularAPI
(http://blog.jooq.org/2013/03/30/howtodesignagoodregularapi/).Today,weregoingtolookintohow

http://blog.jooq.org/category/java/

41/48

3/24/2015

java|Java,SQLandjOOQ.

Java8changestherules

Yes!
Overloadingisanicetooltoprovidecovenienceintwodimensions:
Byprovidingargumenttypealternatives
Byprovidingargumentdefaultvalues
ExamplesfortheabovefromtheJDKinclude:
publicclassArrays{
//Argumenttypealternatives
publicstaticvoidsort(int[]a){...}
publicstaticvoidsort(long[]a){...}
//Argumentdefaultvalues
publicstaticIntStreamstream(int[]array){...}
publicstaticIntStreamstream(int[]array,
intstartInclusive,
intendExclusive){...}
}

http://blog.jooq.org/category/java/
ThejOOQAPIisobviouslyfullofsuchconvenience.AsjOOQisaDSLforSQL(http://www.jooq.org),we 42/48

3/24/2015

java|Java,SQLandjOOQ.

ThejOOQAPIisobviouslyfullofsuchconvenience.AsjOOQisaDSLforSQL(http://www.jooq.org),we
mightevenabusealittlebit:
publicinterfaceDSLContext{
<T1>SelectSelectStep<Record1<T1>>
select(SelectField<T1>field1);
<T1,T2>SelectSelectStep<Record2<T1,T2>>
select(SelectField<T1>field1,
SelectField<T2>field2);
<T1,T2,T3>SelectSelectStep<Record3<T1,T2,T3>>s
select(SelectField<T1>field1,
SelectField<T2>field2,
SelectField<T3>field3);
<T1,T2,T3,T4>SelectSelectStep<Record4<T1,T2,T3,T4>>
select(SelectField<T1>field1,
SelectField<T2>field2,
SelectField<T3>field3,
SelectField<T4>field4);
//andsoon...
}
LanguageslikeCeylontakethisideaofconvenienceonestepfurtherbyclaimingthattheaboveistheonly
reasonablereasonwhyoverloadingisbeusedinJava.Andthus,thecreatorsofCeylonhavecompletely
removedoverloadingfromtheirlanguage,replacingtheabovebyuniontypesandactualdefaultvaluesfor
arguments.E.g.
//Uniontypes
voidsort(int[]|long[]a){...}
//Defaultargumentvalues
IntStreamstream(int[]array,
intstartInclusive=0,
intendInclusive=array.length){...}
ReadTop10CeylonLanguageFeaturesIWishWeHadInJava(http://blog.jooq.org/2013/12/03/top10
ceylonlanguagefeaturesiwishwehadinjava/)formoreinformationaboutCeylon.
InJava,unfortunately,wecannotuseuniontypesorargumentdefaultvalues.Sowehavetouseoverloading
toprovideourAPIconsumerswithconveniencemethods.
Ifyourmethodargumentisafunctionalinterface
(http://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html),however,thingschanged
drasticallybetweenJava7andJava8,withrespecttomethodoverloading.Anexampleisgivenherefrom
JavaFX.
http://blog.jooq.org/category/java/

43/48

3/24/2015

java|Java,SQLandjOOQ.

JavaFXsunfriendlyObservableList
JavaFXenhancestheJDKcollectiontypesbymakingthemobservable.Nottobeconfusedwith
Observable(http://docs.oracle.com/javase/8/docs/api/java/util/Observable.html),a
dinosaurtypefromtheJDK1.0andfrompreSwingdays.
JavaFXsownObservable
(http://docs.oracle.com/javafx/2/api/javafx/beans/Observable.html)essentiallylookslikethis:
publicinterfaceObservable{
voidaddListener(InvalidationListenerlistener);
voidremoveListener(InvalidationListenerlistener);
}
Andluckily,thisInvalidationListener
(http://docs.oracle.com/javafx/2/api/javafx/beans/InvalidationListener.html)isafunctional
interface:
@FunctionalInterface
publicinterfaceInvalidationListener{
voidinvalidated(Observableobservable);
}
Thisisgreat,becausewecandothingslike:
Observableawesome=
FXCollections.observableArrayList();
awesome.addListener(fantastic>splendid.cheer());
(noticehowIvereplacedfoo/bar/bazwithmorecheerfulterms.Weshouldalldothat.Fooandbarareso
1970(http://en.wikipedia.org/wiki/Foobar))
Unfortunately,thingsgetmorehairywhenwedowhatwewouldprobablydo,instead.I.e.insteadof
declaringanObservable,wedlikethattobeamuchmoreusefulObservableList
(http://docs.oracle.com/javafx/2/api/javafx/collections/ObservableList.html):
ObservableList<String>awesome=
FXCollections.observableArrayList();
awesome.addListener(fantastic>splendid.cheer());
Butnow,wegetacompilationerroronthesecondline:

http://blog.jooq.org/category/java/

44/48

3/24/2015

java|Java,SQLandjOOQ.

awesome.addListener(fantastic>splendid.cheer());
//^^^^^^^^^^^
//ThemethodaddListener(ListChangeListener<?superString>)
//isambiguousforthetypeObservableList<String>
Because,essentially
publicinterfaceObservableList<E>
extendsList<E>,Observable{
voidaddListener(ListChangeListener<?superE>listener);
}
and
@FunctionalInterface
publicinterfaceListChangeListener<E>{
voidonChanged(Change<?extendsE>c);
}
Nowagain,beforeJava8,thetwolistenertypeswerecompletelyunambiguouslydistinguishable,andthey
stillare.Youcaneasilycallthembypassinganamedtype.Ouroriginalcodewouldstillworkifwewrote:
ObservableList<String>awesome=
FXCollections.observableArrayList();
InvalidationListenerhearYe=
fantastic>splendid.cheer();
awesome.addListener(hearYe);
Or
ObservableList<String>awesome=
FXCollections.observableArrayList();
awesome.addListener((InvalidationListener)
fantastic>splendid.cheer());
Oreven
ObservableList<String>awesome=
FXCollections.observableArrayList();
awesome.addListener((Observablefantastic)>
splendid.cheer());

http://blog.jooq.org/category/java/
Allofthesemeasureswillremoveambiguity.Butfrankly,lambdasareonlyhalfascoolifyouhaveto

45/48

3/24/2015

java|Java,SQLandjOOQ.

Allofthesemeasureswillremoveambiguity.Butfrankly,lambdasareonlyhalfascoolifyouhaveto
explicitlytypethelambda,ortheargumenttypes.WehavemodernIDEsthatcanperformautocompletion
andhelpinfertypesjustasmuchasthecompileritself.
ImagineifwereallywantedtocalltheotheraddListener()method,theonethattakesa
ListChangeListener.Wedhavetowriteanyof
ObservableList<String>awesome=
FXCollections.observableArrayList();
//Agh.Rememberthatwehavetorepeat"String"here
ListChangeListener<String>hearYe=
fantastic>splendid.cheer();
awesome.addListener(hearYe);
Or
ObservableList<String>awesome=
FXCollections.observableArrayList();
//Agh.Rememberthatwehavetorepeat"String"here
awesome.addListener((ListChangeListener<String>)
fantastic>splendid.cheer());

Oreven
ObservableList<String>awesome=
FXCollections.observableArrayList();
//WTF..."extends"String??Butthat'swhatthisthingneeds...
awesome.addListener((Change<?extendsString>fantastic)>
splendid.cheer());

Overloadyoushant.Bewaryyoumust.
APIdesignishard.Itwashardbefore,ithasgottenhardernow.WithJava8,ifanyofyourAPImethods
argumentsareafunctionalinterface,thinktwiceaboutoverloadingthatAPImethod.Andonceyouve
concludedtoproceedwithoverloading,thinkagain,athirdtimewhetherthisisreallyagoodidea.
Notconvinced?HaveacloselookattheJDK.Forinstancethejava.util.stream.Stream
(http://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html)type.Howmany
overloadedmethodsdoyouseethathavethesamenumberoffunctionalinterfacearguments,whichagain
http://blog.jooq.org/category/java/

46/48

3/24/2015

java|Java,SQLandjOOQ.

takethesamenumberofmethodarguments(asinourpreviousaddListener()example)?
Zero.
Thereareoverloadswhereoverloadargumentnumbersdiffer.Forinstance:
<R>Rcollect(Supplier<R>supplier,
BiConsumer<R,?superT>accumulator,
BiConsumer<R,R>combiner);
<R,A>Rcollect(Collector<?superT,A,R>collector);
Youwillneverhaveanyambiguitywhencallingcollect().
Butwhentheargumentnumbersdonotdiffer,andneitherdotheargumentsownmethodargument
numbers,themethodnamesaredifferent.Forinstance:
<R>Stream<R>map(Function<?superT,?extendsR>mapper);
IntStreammapToInt(ToIntFunction<?superT>mapper);
LongStreammapToLong(ToLongFunction<?superT>mapper);
DoubleStreammapToDouble(ToDoubleFunction<?superT>mapper);
Now,thisissuperannoyingatthecallsite,becauseyouhavetothinkinadvancewhatmethodyouhaveto
usebasedonavarietyofinvolvedtypes.
Butitsreallytheonlysolutiontothisdilemma.So,remember:
YouWillRegretApplyingOverloadingwithLambdas!
Didyoulikethisarticle?Youmightalsolike:
HowtoDesignaGood,RegularAPI(http://blog.jooq.org/2013/03/30/howtodesignagoodregularapi/)
10SubtleBestPracticeswhenCodingJava(http://blog.jooq.org/2013/08/20/10subtlebestpracticeswhen
codingjava/)
KeepingthingsDRY:Methodoverloading(http://blog.jooq.org/2014/07/21/keepingthingsdrymethod
overloading/)
Olderposts
Java,SQLandjOOQ.
BlogatWordPress.com.TheSkepticalTheme.
Follow

FollowJava,SQLandjOOQ.
http://blog.jooq.org/category/java/

47/48

3/24/2015

java|Java,SQLandjOOQ.

BuildawebsitewithWordPress.com

http://blog.jooq.org/category/java/

48/48

You might also like