Programmering

JDK 7: Diamantoperatøren

Project Coin tilbyr mange "små språkforbedringer" som en delmengde av de nye JDK 7-funksjonene. Jeg blogget nylig på Project Coin som slår på strenger, og i dette innlegget skriver jeg om den nye Diamond Operator ().

Diamond Operator reduserer noe av Javas ordlighetsgrad rundt generikk ved å la kompilatoren utlede parametertyper for konstruktører av generiske klasser. Det opprinnelige forslaget om å legge Diamond Operator til Java-språket ble laget i februar 2009 og inkluderer dette enkle eksemplet:

Tenk for eksempel på følgende oppgaveuttalelse:

Kart anagrammer = nye HashMap();

Dette er ganske lang, så det kan erstattes med dette:

Kart anagrammer = nye HashMap ();

Ovennevnte eksempel gitt i Jeremy Mansons forslag (som var et av de første som svar på en oppfordring til Project Coin-ideer) er enkelt, men viser tilstrekkelig hvordan diamantoperatøren brukes i JDK 7. Mansons forslag gir også betydelig betydning for hvorfor dette tillegget var ønskelig:

Kravet om at typeparametere dupliseres unødvendig som

dette oppmuntrer en uheldig

overflod av statiske fabrikkmetoder, rett og slett fordi type inferens

jobber med metodeinnkallinger.

Med andre ord, JDK 7 Project Coin-tilførsel av en diamantoperatør gir typeavledning til konstruktører som har vært tilgjengelig med metoder. Med metoder gjøres typeavledning implisitt når man slipper den eksplisitte parametertypespesifikasjonen. Med instantiering, derimot, må diamantoperatøren spesifiseres eksplisitt for å "fortelle" kompilatoren å utlede typen.

I sitt opprinnelige forslag påpeker Manson at syntaksen uten en spesiell diamantoperatør ikke kunne brukes til implisitt å utlede typer for instantiasjoner fordi "for bakoverkompatibilitet indikerer new Map () en rå type, og kan derfor ikke brukes til type slutning. " Siden Type Inference i Generics Lesson of the Learning the Java Language trail of the Java Tutorials inkluderer en seksjon kalt "Type Inference and Instantiation of Generic Classes" som allerede er oppdatert for å gjenspeile Java SE 7. Denne delen beskriver også hvorfor spesialen operatøren må spesifiseres for å eksplisitt informere kompilatoren om å bruke typeslutning ved instantiering:

Vær oppmerksom på at du må spesifisere diamantoperatøren for å dra nytte av automatisk typeinferanse under generell klasseinstansiering. I det følgende eksemplet genererer kompilatoren en ukontrollert konverteringsadvarsel fordi HashMap () -konstruktøren refererer til HashMap-rå typen, ikke Map type

I Item 24 ("Eliminate Unchecked Warnings") i den andre utgaven av Effective Java, understreker Josh Bloch i dristig tekst, "Fjern alle ukontrollerte advarsler du kan." Bloch viser et eksempel på den ukontrollerte konverteringsadvarselen som oppstår når man kompilerer kode som bruker en rå type på høyre side av en erklæring. Neste kodeliste viser kode som vil føre til denne advarselen.

endelig Kart statesToCities = ny HashMap (); // rå! 

De neste to skjermbildene viser kompilatorens svar på ovennevnte kodelinje. Det første bildet viser meldingen når det ikke er aktivert -Xlint-advarsler, og det andre viser den mer eksplisitte advarselen som oppstår når -Xlint: ukontrollert er gitt som et argument til javac.

Hvis Effektiv Java, Påpeker Bloch at denne spesielle ukontrollerte advarselen er enkel å adressere ved eksplisitt å gi parametertypen til instantiering av generisk klasse. Med JDK 7 blir dette enda enklere! I stedet for å måtte legge til den eksplisitte teksten med disse typenavnene, kan typene utledes i mange tilfeller, og spesifikasjonen til diamantoperatøren ber kompilatoren om å gjøre denne slutningen i stedet for å bruke rå typen.

Den neste Java-kodelisten gir enkle eksempler på disse konseptene. Det er metoder som demonstrerer instantiering av et rått sett, instantiering av et sett med eksplisitt spesifikasjon av parametertypen og instantiering av et sett med parametertype utledet på grunn av spesifikasjon av diamantoperatøren ().

pakke dustin. eksempler; importere java.util.HashMap; importere java.util.HashSet; importere java.util.Map; importere java.util.Set; importere statisk java.lang.System.out; / ** * Veldig enkel demonstrasjon av JDK 7 / Project Coin's "Diamond Operator." * / public class DiamondOperatorDemo {/ ** Bruk av "rå" type. * / private static Set rawWithoutExplicitTyping () {final Set names = new HashSet (); addNames (navn); returnere navn; } / ** Angir eksplisitt generisk klasses parametertype for instantiering. * / private static Set explicitTypingExplicitlySpecified () {final Set names = new HashSet (); addNames (navn); returnere navn; } / ** * Inferring generisk klasse instantiering parameter type med JDK 7s * 'Diamond Operator.' * / private static Set explicitTypingInferredWithDiamond () {final Set names = new HashSet (); addNames (navn); returnere navn; } private statiske ugyldige addNames (final Set namesToAddTo) {namesToAddTo.add ("Dustin"); namesToAddTo.add ("Rett"); namesToAddTo.add ("Homer"); } / ** * Hoved kjørbar funksjon. * / public static void main (final String [] argumenter) {out.println (rawWithoutExplicitTyping ()); out.println (explicitTypingExplicitlySpecified ()); out.println (explicitTypingInferredWithDiamond ()); }} 

Når koden ovenfor er samlet, er det bare den "rå" saken som fører til en advarsel.

På dette punktet kan det være innsiktsfullt å se på hva javap forteller oss om disse tre metodene. Dette gjøres i dette tilfellet med kommandoen (-v alternativ for verbose gir alle saftige detaljer og -p viser disse saftige detaljene for privat metoder):

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

Fordi disse metodene var i en enkelt klasse, er det en enkelt strøm av utdata for hele klassen. For å gjøre det lettere å sammenligne dem, har jeg imidlertid kuttet og limt inn utdataene i et format som justerer javap-utgangen for hver metode mot hverandre. Hver kolonne representerer javap output for en av metodene. Jeg har endret skriftfargen til den aktuelle metoden til blå for å få den til å skille seg ut og merke kolonnens utdata.

Annet enn navnene på selve metodene, er det INGEN forskjell i javap produksjon. Dette er fordi Java generics type sletting betyr at differensiering basert på type ikke er tilgjengelig på kjøretid. Java Tutorial on Generics inneholder en side som heter Type Erasure som forklarer dette:

Kompilatoren fjerner all informasjon om selve argumentargumentet på kompileringstidspunktet.

Type sletting eksisterer slik at ny kode kan fortsette å grensesnitt med eldre kode. Å bruke en rå type av annen grunn regnes som dårlig programmeringspraksis og bør unngås når det er mulig.

Som sitatet ovenfor minner oss om, betyr sletting at å bytekode en rå type ikke er annerledes enn en eksplisitt skrevet parametertype, men oppfordrer også utviklere til å ikke bruke rå typer bortsett fra å integrere med eldre kode.

Konklusjon

Inkluderingen av diamantoperatøren () i Java SE 7 betyr at kode som instantierer generiske klasser kan være mindre ordrik. Kodespråk generelt, og Java spesielt, beveger seg mot ideer som konvensjon over konfigurasjon, konfigurasjon unntaksvis, og utleder ting så ofte som mulig i stedet for å kreve eksplisitt spesifikasjon. Dynamisk skrevne språk er godt kjent for type inferens, men selv statisk skrevet Java kan gjøre mer av dette enn det gjør, og diamantoperatøren er et eksempel på dette.

Opprinnelig innlegg tilgjengelig på //marxsoftware.blogspot.com/

Denne historien, "JDK 7: The Diamond Operator" ble opprinnelig utgitt av JavaWorld.

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