Programiranje

JDK 7: Diamantni operater

Project Coin ponuja številne "majhne jezikovne izboljšave" kot podskupino novih funkcij JDK 7. Pred kratkim sem blogiral o preklopu na strune Project Coin in v tej objavi pišem o novem Diamond Operatorju ().

Diamond Operator zmanjša nekaj dvoumnosti Java, ki obdaja generike, tako da prevajalnik sklepa na tipe parametrov za konstruktorje generičnih razredov. Prvotni predlog za dodajanje Diamond Operatorja v jezik Java je bil podan februarja 2009 in vključuje ta preprost primer:

Upoštevajte na primer naslednjo izjavo o dodelitvi:

Zemljevid anagrams = nov HashMap();

To je precej dolgo, zato ga lahko nadomestimo s tem:

Zemljevid anagrami = nov HashMap ();

Zgornji primer v predlogu Jeremyja Mansona (ki se je med prvimi odzval na razpis za ideje o projektnih kovancih) je preprost, vendar primerno prikazuje, kako se Diamond Operator uporablja v JDK 7. Mansonov predlog tudi bistveno pojasnjuje, zakaj ta dodatek je bilo zaželeno:

Zahteva, da se parametri tipa podvajajo po nepotrebnem, je všeč

to spodbuja nesrečnika

prekomerno število statičnih tovarniških metod, preprosto zato, ker sklepanje o tipu

dela na klicih metode.

Z drugimi besedami, dodajanje diamantnega operaterja JDK 7 Project Coin prinaša tipe sklepanja konstruktorjem, ki so na voljo z metodami. Pri metodah se sklepanje na tipe naredi implicitno, ko izpustite eksplicitno specifikacijo tipa parametra. Po drugi strani pa je treba z instanciranjem operaterja diamantov izrecno navesti, da prevajalniku "pove", da sklepa na tip.

V svojem prvotnem predlogu Manson poudarja, da sintakse brez posebnega diamantnega operaterja ni mogoče uporabiti za implicitno sklepanje na tipe za instanciranje, ker "za nazaj združljivost new Map () označuje surov tip in ga zato ni mogoče uporabiti za tip sklepanje. " Na strani o vnosu tipov v Lekciji o generičnem učenju sledi učenja jezika Java v vajah Java je odsek z naslovom "Sklepanje na tipe in namestitev generičnih razredov", ki je že posodobljen, da odraža Java SE 7. Ta odstavek opisuje tudi, zakaj mora biti naveden operator, da bo prevajalnik izrecno obvestil, da mora uporabiti sklepanje o tipu pri instanciranju:

Če želite izkoristiti samodejno sklepanje o tipu med generiranjem primerka razreda, morate določiti diamantnega operaterja. V naslednjem primeru prevajalnik ustvari nepreverjeno opozorilo o pretvorbi, ker se konstruktor HashMap () nanaša na surov tip HashMap in ne na Map tip

Josh Bloch v točki 24 ("Odpravi nepreverjena opozorila") druge izdaje učinkovite Jave poudarja v krepko besedilo, "Odpravite vsako nepreverjeno opozorilo, ki ga lahko." Bloch prikazuje primer nepreverjenega opozorila o pretvorbi, ki se pojavi, ko sestavi kodo, ki uporablja neobdelani tip na desni strani izjave. Naslednji seznam kode prikazuje kodo, ki bo vodila do tega opozorila.

končni zemljevid stateToCities = nov HashMap (); // surov! 

Naslednja dva posnetka zaslona prikazujeta odziv prevajalnika na zgornjo vrstico kode. Prva slika prikazuje sporočilo, če niso omogočena opozorila -Xlint, druga pa bolj eksplicitno opozorilo, ki se pojavi, ko -Xlint: nepotrjeno je naveden kot argument za javac.

Če Učinkovita Java, Bloch poudarja, da je to posebno nepreverjeno opozorilo enostavno nasloviti z izrecnim podajanjem tipa parametra za instanciranje generičnega razreda. Z JDK 7 bo to še lažje! Namesto da bi bilo treba dodati eksplicitno besedilo s temi imeni tipov, lahko v mnogih primerih sklepamo na tipe, specifikacija operaterja diamantov pa prevajalniku pove, da namesto tega uporabi surovo vrsto.

Naslednji seznam kod Java vsebuje poenostavljene primere teh konceptov. Obstajajo metode, ki prikazujejo instanciranje surovega niza, instanciranje niza z izrecno navedbo njegovega tipa parametra in instanciranje niza s tipom parametra, izpeljanega zaradi specifikacije diamantnega operaterja ().

paket prah v.primeri; uvoz java.util.HashMap; uvoz java.util.HashSet; uvoz java.util.Map; import java.util.Set; uvoz statičnega java.lang.System.out; / ** * Zelo preprost prikaz JDK 7's / Project Coin "Diamond Operator." * / javni razred DiamondOperatorDemo {/ ** Uporaba "surovega" tipa. * / private static Set rawWithoutExplicitTyping () {final set names = new HashSet (); addNames (imena); vrni imena; } / ** Izrecno podaja vrsto parametra instance za generični razred. * / zasebni statični nabor eksplicitnoTypingExplicitlySpecified () {končna imena nizov = nov HashSet (); addNames (imena); vrni imena; } / ** * Navedba vrste parametra za instanciranje generičnega razreda z JDK 7 * 'Diamond Operator.' * / zasebni statični nabor eksplicitnoTypingInferredWithDiamond () {končni nabor imen = nov HashSet (); addNames (imena); vrni imena; } zasebna statična praznina addNames (končni Set namesToAddTo) {namesToAddTo.add ("Dustin"); namesToAddTo.add ("Rett"); namesToAddTo.add ("Homer"); } / ** * Glavna izvršljiva funkcija. * / javni statični void glavni (končni argumenti String []) {out.println (rawWithoutExplicitTyping ()); out.println (eksplicitnoTypingExplicitlySpecified ()); out.println (eksplicitnoTypingInferredWithDiamond ()); }} 

Ko je zgornja koda sestavljena, opozorilo pripelje samo v primeru "raw".

Na tej točki je lahko pronicljivo pogledati, kaj nam javap sporoča o teh treh metodah. To se v tem primeru naredi z ukazom (-v možnost za več besed daje vse sočne podrobnosti in -p prikaže te sočne podrobnosti za zasebno metode):

razredi javap -v -p -classpath dustin.examples.DiamondOperatorDemo 

Ker so bile vse metode v enem razredu, je za celoten razred na voljo en tok rezultatov. Da pa jih lažje primerjam, sem izrez izrezal in prilepil v obliko, ki poravna izhod javap za vsako metodo drug proti drugemu. Vsak stolpec predstavlja javap izhod za eno od metod. Barvo pisave določene metode sem spremenil v modro, da je izstopala in označil izhod tega stolpca.

Razen imen samih metod v NIKOLJI ni razlike javap izhod. To je zato, ker brisanje generičnega tipa Java pomeni, da razlikovanje glede na tip med izvajanjem ni na voljo. Vadnica Java o generiki vključuje stran z imenom Type Erasure, ki pojasnjuje to:

Prevajalnik odstrani vse informacije o dejanskem argumentu tipa v času prevajanja.

Izbris tipa obstaja, tako da se lahko nova koda še naprej povezuje s staro kodo. Uporaba surove vrste iz katerega koli drugega razloga se šteje za slabo programsko prakso in se ji je treba izogibati, kadar je to mogoče.

Kot nas opominja zgornji citat, izbris pomeni, da se bytecode surovega tipa ne razlikuje od izrecno vpisanega tipa parametra, hkrati pa spodbuja razvijalce, da ne uporabljajo surovih tipov, razen za integracijo s staro kodo.

Zaključek

Vključitev diamantnega operaterja () v Java SE 7 pomeni, da je koda, ki ustvari generične razrede, lahko manj podrobna. Kodirajoči jeziki na splošno in zlasti Java se premikajo k idejam, kot so dogovor o konfiguraciji, konfiguracija po izjemi in sklepanje stvari čim pogosteje, namesto da bi zahtevali izrecno navedbo. Dinamično natipkani jeziki so dobro znani po sklepanju na tipe, toda tudi statično natipkana Java lahko stori več kot to, kar je primer diamantnega operaterja.

Izvirna objava je na voljo na //marxsoftware.blogspot.com/

To zgodbo "JDK 7: Diamond Operator" je prvotno objavil JavaWorld.

$config[zx-auto] not found$config[zx-overlay] not found