More than you ever wanted to know about Java...

23
More than you ever wanted to know about Java Generics Jeff Meister CMSC 420 Summer 2007

Transcript of More than you ever wanted to know about Java...

Page 1: More than you ever wanted to know about Java Genericsmeesh/420/ContentBook/FormalNotes/JAVANote… · Generics • Don’t try to think about generic code abstractly; make an example

Morethanyoueverwantedtoknowabout

JavaGenericsJeffMeister

CMSC420Summer2007

Page 2: More than you ever wanted to know about Java Genericsmeesh/420/ContentBook/FormalNotes/JAVANote… · Generics • Don’t try to think about generic code abstractly; make an example

GENERICS:AYOUNGLADY’SILLUSTRATEDPRIMERINFOURSLIDES

Theobligatoryreviewoftheboringstuff,or…

Page 3: More than you ever wanted to know about Java Genericsmeesh/420/ContentBook/FormalNotes/JAVANote… · Generics • Don’t try to think about generic code abstractly; make an example

Java1.4:LifeBeforeGenerics

Javacodeusedtolooklikethis:

ListlistOfFruits=newArrayList();listOfFruits.add(newFruit(“Apple”));Fruitapple=(Fruit)listOfFruits.remove(0);listOfFruits.add(newVegetable(“Carrot”));//Whoops!Fruitorange=(Fruit)listOfFruits.remove(0);//Run‐timeerror

Problem:Compilerdoesn’tknowlistOfFruits shouldonlycontainfruits

Page 4: More than you ever wanted to know about Java Genericsmeesh/420/ContentBook/FormalNotes/JAVANote… · Generics • Don’t try to think about generic code abstractly; make an example

ASillySoluMon

Wecouldmakeourownfruit‐onlylistclass:

classFruitList{voidadd(Fruitelement){…}Fruitremove(intindex){…}…}

Butwhataboutwhenwewantavegetable‐onlylistlater?Copy‐paste?Lotsofbloated,unmaintainablecode?

Page 5: More than you ever wanted to know about Java Genericsmeesh/420/ContentBook/FormalNotes/JAVANote… · Generics • Don’t try to think about generic code abstractly; make an example

Java1.5:NowWe’reTalking

Now,Javacodelookslikethis:

List<Fruit>listOfFruits=newArrayList<Fruit>();listOfFruits.add(newFruit(“Apple”));Fruitapple=listOfFruits.remove(0);listOfFruits.add(newVegetable(“Carrot”));//Compile‐timeerror

Hooray!CompilernowknowslistOfFruitscontainsonlyFruits

•  Soremove()mustreturnaFruit•  Andadd()cannottakeaVegetable

Page 6: More than you ever wanted to know about Java Genericsmeesh/420/ContentBook/FormalNotes/JAVANote… · Generics • Don’t try to think about generic code abstractly; make an example

Youguysrememberthis,right?

Here’showwe’dwritethatgenericListclass:

classList<T>{voidadd(Telement){…}Tremove(intindex){…}…}

Problemsolved!SimplyinvokeList<Fruit>,List<Vegetable>,andsoon.I’msureyou’vewri^encodelikethisbefore,solet’smoveto…

Page 7: More than you ever wanted to know about Java Genericsmeesh/420/ContentBook/FormalNotes/JAVANote… · Generics • Don’t try to think about generic code abstractly; make an example

THEFUNSTUFFHopeyouplannedonbeingconfusedtoday,becauseit’sMmefor…

Page 8: More than you ever wanted to know about Java Genericsmeesh/420/ContentBook/FormalNotes/JAVANote… · Generics • Don’t try to think about generic code abstractly; make an example

AbandonAllHope…

•  Genericsimplementparametricpolymorphism– Parametric:Thetypeparameter(e.g.,<T>)…– Polymorphism:…cantakemanyforms

•  However,ifwe’regoingtoprogramwithparameterizedtypes,weneedtounderstandhowthelanguagerulesapplytothem

•  Javagenericsareimplementedusingtypeerasure,whichleadstoallsortsofwackyissues,aswe’llsee

Page 9: More than you ever wanted to know about Java Genericsmeesh/420/ContentBook/FormalNotes/JAVANote… · Generics • Don’t try to think about generic code abstractly; make an example

Subtyping

SinceAppleisasubtypeofObject,isList<Apple>asubtypeofList<Object>?

List<Apple>apples=newArrayList<Apple>();List<Object>objs=apples;//Doesthiscompile?

Seemsharmless,butno!Ifthatworked,wecouldputOrangesinourList<Apple>likeso:

objs.add(newOrange());//OKbecauseobjsisaList<Object>Applea=apples.remove(0);//WouldassignOrangetoApple!

Page 10: More than you ever wanted to know about Java Genericsmeesh/420/ContentBook/FormalNotes/JAVANote… · Generics • Don’t try to think about generic code abstractly; make an example

AnAside:SubtypingandJavaArrays

•  Javaarraysactuallyhavethesubtypingproblemjustdescribed(theyarecovariant)

•  Thefollowingobviouslywrongcodecompiles,onlytofailatrun‐Mme:

Apple[]apples=newApple[3];Object[]objs=apples;//Thecompilerpermitsthis!objs[0]=newOrange();//ArrayStoreException

•  Avoidmixingarraysandgenerics(trustme)

Page 11: More than you ever wanted to know about Java Genericsmeesh/420/ContentBook/FormalNotes/JAVANote… · Generics • Don’t try to think about generic code abstractly; make an example

WildcardTypes

•  So,whatisList<Apple>asubtypeof?•  ThesupertypeofallkindsoflistsisList<?>,theListofunknown

•  The?isawildcardthatmatchesanything

•  Wecan’taddthings(exceptnull)toaList<?>,sincewedon’tknowwhattheListisreallyof

•  ButwecanretrievethingsandtreatthemasObjects,sinceweknowtheyareatleastthat

Page 12: More than you ever wanted to know about Java Genericsmeesh/420/ContentBook/FormalNotes/JAVANote… · Generics • Don’t try to think about generic code abstractly; make an example

BoundedWildcards

•  Wildcardtypescanhaveupperandlowerbounds

•  AList<?extendsFruit>isaListofitemsthathaveunknowntypebutareallatleastFruits– SoitcancontainFruitsandApplesbutnotPeas

•  AList<?superFruit>isaListofitemsthathaveunknowntypebutareallatmostFruits– SoitcancontainFruitsandObjectsbutnotApples

Page 13: More than you ever wanted to know about Java Genericsmeesh/420/ContentBook/FormalNotes/JAVANote… · Generics • Don’t try to think about generic code abstractly; make an example

BoundedWildcardsExampleclassWholesaleVendor<T>{voidbuy(inthowMany,List<?superT>fillMeUp){…}voidsell(List<?extendsT>emptyMe){…}…}

WholesaleVendor<Fruit>vendor=newWholesaleVendor<Fruit>();List<Food>stock=…;List<Apple>overstockApples=…;

//IcanbuyFoodfromtheFruitvendor:vendor.buy(100,stock);//IcansellmyApplestotheFruitvendor:vendor.sell(overstockApples);

Page 14: More than you ever wanted to know about Java Genericsmeesh/420/ContentBook/FormalNotes/JAVANote… · Generics • Don’t try to think about generic code abstractly; make an example

JoshBloch’sBoundedWildcardsRule

•  Use<?extendsT>whenparameterizedinstanceisaTproducer(forreading/input)

•  Use<?superT>whenparameterizedinstanceisaTconsumer(forwriMng/output)

Uhh…what?

Page 15: More than you ever wanted to know about Java Genericsmeesh/420/ContentBook/FormalNotes/JAVANote… · Generics • Don’t try to think about generic code abstractly; make an example

GenericMethods

•  Youcanparameterizemethodstoo.Here’sasignaturefromtheJavaAPI:

static<T>voidfill(List<?superT>list,Tobj);

•  Easyenough,yeah?Trythisoneonforsize:static<TextendsObject&Comparable<?superT>>T

max(Collection<?extendsT>coll);

•  Youdon’tneedtoexplicitlyinstanMategenericmethods(thecompilerwillfigureitout)

Page 16: More than you ever wanted to know about Java Genericsmeesh/420/ContentBook/FormalNotes/JAVANote… · Generics • Don’t try to think about generic code abstractly; make an example

HowGenericsareImplemented

•  RatherthanchangeeveryJVMbetweenJava1.4and1.5,theychosetouseerasure

•  Agerthecompilerdoesitstypechecking,itdiscardsthegenerics;theJVMneverseesthem!

•  Itworkssomethinglikethis:–  TypeinformaMonbetweenanglebracketsisthrownout,e.g.,List<String>List

– Usesoftypevariablesarereplacedbytheirupperbound(usuallyObject)

–  Castsareinsertedtopreservetype‐correctness

Page 17: More than you ever wanted to know about Java Genericsmeesh/420/ContentBook/FormalNotes/JAVANote… · Generics • Don’t try to think about generic code abstractly; make an example

ProsandConsofErasure

•  Good:BackwardcompaMbilityismaintained,soyoucansMlluselegacynon‐genericlibraries

•  Bad:Youcan’tfindoutwhattypeagenericclassisusingatrun‐Mme:

classExample<T>{voidmethod(Objectitem){if(iteminstanceofT){…}//Compilererror!TanotherItem=newT();//Compilererror!T[]itemArray=newT[10];//Compilererror!}}

Page 18: More than you ever wanted to know about Java Genericsmeesh/420/ContentBook/FormalNotes/JAVANote… · Generics • Don’t try to think about generic code abstractly; make an example

UsingLegacyCodeinGenericCode

•  SayIhavesomegenericcodedealingwithFruits,butIwanttocallthislegacylibraryfuncMon:

SmoothiemakeSmoothie(Stringname,Listfruits);

•  IcanpassinmygenericList<Fruit>forthefruitsparameter,whichhastherawtypeList.Butwhy?Thatseemsunsafe…makeSmoothie()couldsMckaVegetableinthelist,andthatwouldtastenasty!

Page 19: More than you ever wanted to know about Java Genericsmeesh/420/ContentBook/FormalNotes/JAVANote… · Generics • Don’t try to think about generic code abstractly; make an example

RawTypesandGenericTypes

•  Listdoesn’tmeanList<Object>,becausethenwecouldn’tpassinaList<Fruit>(subtyping,remember?)

•  Listdoesn’tmeanList<?>either,becausethenwecouldn’tassignaListtoaList<Fruit>(whichisalegaloperaMon)

•  Weneedbothofthesetoworkforgenericcodetointeroperatewithlegacycode

•  Rawtypesbasicallyworklikewildcardtypes,justnotcheckedasstringently–  TheseoperaMonsgenerateanuncheckedwarning

Page 20: More than you ever wanted to know about Java Genericsmeesh/420/ContentBook/FormalNotes/JAVANote… · Generics • Don’t try to think about generic code abstractly; make an example

TheProblemwithLegacyCode

•  “Callinglegacycodefromgenericcodeisinherentlydangerous;onceyoumixgenericcodewithnon‐genericlegacycode,allthesafetyguaranteesthatthegenerictypesystemusuallyprovidesarevoid.However,youaresMllbe^eroffthanyouwerewithoutusinggenericsatall.Atleastyouknowthecodeonyourendisconsistent.”–GiladBracha,JavaGenericsDeveloper

Page 21: More than you ever wanted to know about Java Genericsmeesh/420/ContentBook/FormalNotes/JAVANote… · Generics • Don’t try to think about generic code abstractly; make an example

MyAdviceonGenerics

•  Don’ttrytothinkaboutgenericcodeabstractly;makeanexampleinstanMaMoninyourheadandrunthroughscenariosusingit

•  Genericsareavaluabletooltoensuretypesafety,sousethem!Letthecompilerhelpyou

•  However,genericsalsocomplicatesyntax,andtheycangeneratesomenastyerrorsthatareapaintounderstandanddebug

Page 22: More than you ever wanted to know about Java Genericsmeesh/420/ContentBook/FormalNotes/JAVANote… · Generics • Don’t try to think about generic code abstractly; make an example

AnAnalogy:FuncMons

•  Problem:IwanttoperformthesamecomputaMononmanydifferentinputvalueswithoutwriMngthecomputaMonoverandover.

•  SoluMon:WriteafuncMon!Useavariabletorepresenttheinputvalue,andwriteyourcodetoperformthecomputaMononthisvariableinawaythatdoesnotdependonitsvalue.NowyoucancallthefuncMonmanyMmes,passingindifferentvaluesforthevariable.Easystuff.

Page 23: More than you ever wanted to know about Java Genericsmeesh/420/ContentBook/FormalNotes/JAVANote… · Generics • Don’t try to think about generic code abstractly; make an example

GenericsProvideAnotherAbstracMon

•  Problem:Iwanttousethesameclass(ormethod)withobjectsofmanydifferenttypeswithoutwriMngtheclassoverandoverorsacrificingtypesafety.

•  SoluMon:Generifytheclass!UseavariableTtorepresenttheinputtype,andwriteyourcodetooperateonobjectsoftypeTinawaythatdoesnotdependontheactualvalueofT.NowyoucaninstanMatetheclassmanyMmes,passingindifferenttypesforT.

•  See?It’snotsobad.Genericsjustallowyoutoabstractovertypesinsteadofvalues.