Feste verdier til Java Enum

1. Introduksjon

Java enum type gir en språkstøttet måte å skape og bruke konstante verdier på. Ved å definere et endelig verdisett, vil enum er mer typesikker enn konstante bokstavlige variabler som String eller int.

Derimot, enum verdier kreves for å være gyldige identifikatorer, og vi oppfordres til å bruke SCREAMING_SNAKE_CASE etter konvensjon.

Gitt disse begrensningene, de enum verdi alene er ikke egnet for menneskelesbare strenger eller ikke-strengverdier.

I denne opplæringen bruker vi enumHar funksjoner som en Java-klasse for å feste verdiene vi ønsker.

2. Bruke Java Enum som en klasse

Vi lager ofte en enum som en enkel liste over verdier. Her er for eksempel de to første radene i det periodiske systemet som en enkel enum:

offentlig enum Element {H, HE, LI, BE, B, C, N, O, F, NE}

Ved hjelp av syntaksen ovenfor har vi opprettet ti statiske, endelige forekomster av enum heter Element. Selv om dette er veldig effektivt, har vi bare fanget element-symbolene. Og mens store bokstaver er passende for Java-konstanter, er det ikke slik vi normalt skriver symbolene.

Videre mangler vi også andre egenskaper til elementene i det periodiske systemet, som navnet og atomvekten.

Selv om enum type har spesiell oppførsel i Java, kan vi legge til konstruktører, felt og metoder som vi gjør med andre klasser. På grunn av dette kan vi forbedre vår enum å inkludere verdiene vi trenger.

3. Legge til en konstruktør og et siste felt

La oss starte med å legge til elementnavnene. Vi setter navnene til a endelig variabel ved hjelp av en konstruktør:

offentlig enum Element {H ("Hydrogen"), HE ("Helium"), // ... NE ("Neon"); offentlig slutt String label; private Element (strengetikett) {this.label = label; }}

Først og fremst legger vi merke til den spesielle syntaksen i erklæringslisten. Slik påkalles en konstruktør for enum typer. Selv om det er ulovlig å bruke ny operatør for en enum, kan vi sende konstruktørargumenter i erklæringslisten.

Vi erklærer deretter en forekomstvariabel merkelapp. Det er noen ting å merke seg om det.

For det første valgte vi merkelapp identifikator i stedet for Navn. Selv om medlemsfeltet Navn er tilgjengelig for bruk, la oss velge merkelapp for å unngå forveksling med det forhåndsdefinerte Enum.name () metode.

For det andre, våre merkelapp feltet er endelig. Mens felt av en enum trenger ikke være endelig, i de fleste tilfeller vil vi ikke at etikettene våre skal endres. I ånden av enum verdiene er konstante, dette gir mening.

Til slutt, merkelapp feltet er offentlig. Derfor kan vi få tilgang til etiketten direkte:

System.out.println (BE.label);

På den annen side kan feltet være privat, åpnes med en getLabel () metode. For kortfattede formål vil denne artikkelen fortsette å bruke den offentlige feltstilen.

4. Finne Java Enum Verdier

Java gir en valueOf (streng) metode for alle enum typer. Dermed kan vi alltid få en enum verdi basert på det deklarerte navnet:

assertSame (Element.LI, Element.valueOf ("LI"));

Imidlertid kan det være lurt å slå opp en enum verdi av vårt etikettfelt også. For å gjøre det kan vi legge til en statisk metode:

public static Element valueOfLabel (Strengetikett) {for (Element e: values ​​()) {if (e.label.equals (label)) {return e; }} returner null; }

Det statiske valueOfLabel () metoden itererer Element verdier til den finner samsvar. Det kommer tilbake null hvis ingen samsvar blir funnet. Motsatt kan et unntak kastes i stedet for å returnere null.

La oss se et raskt eksempel ved å bruke vår valueOfLabel () metode:

assertSame (Element.LI, Element.valueOfLabel ("Lithium"));

5. Caching av oppslagsverdiene

Vi kan unngå å iterere enum verdier ved å bruke a Kart for å cache etikettene. For å gjøre dette definerer vi a statisk endelig Kart og fyll den når klassen lastes:

offentlig enum Element {// ... enum verdsetter privat statisk slutt Kart BY_LABEL = ny HashMap (); statisk {for (Element e: verdier ()) {BY_LABEL.put (e.label, e); }} // ... felt, konstruktør, metoder offentlig statisk Element valueOfLabel (strengetikett) {return BY_LABEL.get (label); }}

Som et resultat av å bli bufret, har enum verdiene gjentas bare en gang, og valueOfLabel () metoden er forenklet.

Som et alternativ kan vi i lett form konstruere hurtigbufferen når den først er tilgjengelig i valueOfLabel () metode. I så fall må karttilgang synkroniseres for å forhindre samtidighetsproblemer.

6. Legge til flere verdier

De Enum konstruktør kan godta flere verdier. For å illustrere, la oss legge til atomnummeret som et int og atomvekten som en flyte:

offentlig enum Element {H ("Hydrogen", 1, 1.008f), HE ("Helium", 2, 4.0026f), // ... NE ("Neon", 10, 20.180f); privat statisk endelig Kart BY_LABEL = ny HashMap (); privat statisk sluttkart BY_ATOMIC_NUMBER = nytt HashMap (); privat statisk sluttkart BY_ATOMIC_WEIGHT = nytt HashMap (); statisk {for (Element e: verdier ()) {BY_LABEL.put (e.label, e); BY_ATOMIC_NUMBER.put (e.atomicNumber, e); BY_ATOMIC_WEIGHT.put (e.atomicWeight, e); }} offentlig endelig strengmerke; offentlig endelig int atomicNumber; offentlig endelig flyte atomvekt; private Element (String label, int atomicNumber, float atomicWeight) {this.label = label; this.atomicNumber = atomicNumber; this.atomicWeight = atomicWeight; } offentlig statisk elementverdiOfLabel (strengetikett) {return BY_LABEL.get (label); } offentlig statisk elementverdiOfAtomicNumber (int-nummer) {return BY_ATOMIC_NUMBER.get (number); } offentlig statisk elementverdiOfAtomicWeight (float weight) {return BY_ATOMIC_WEIGHT.get (weight); }}

På samme måte kan vi legge til eventuelle verdier vi ønsker i enum, for eksempel de riktige sakssymbolene, "Han", "Li" og "Vær", for eksempel.

Videre kan vi legge til beregnede verdier til våre enum ved å legge til metoder for å utføre operasjoner.

7. Kontrollere grensesnittet

Som et resultat av å legge til felt og metoder i vår enum, har vi endret det offentlige grensesnittet. Derfor koden vår, som bruker kjernen EnumNavn() og verdien av() metoder, vil være uvitende om våre nye felt.

De statiskverdien av() metoden er allerede definert for oss av Java-språket. Derfor kan vi ikke tilby våre egne verdien av() gjennomføring.

På samme måte, fordi det Enum.name () metoden er endelig, vi kan ikke overstyre det heller.

Som et resultat er det ingen praktisk måte å utnytte våre ekstra felt ved å bruke standarden Enum API. La oss i stedet se på noen forskjellige måter å avsløre feltene våre på.

7.1. Overstyring toString ()

Overstyring toString () kan være et alternativ til overordnet Navn():

@Override public String toString () {return this.label; }

Som standard, Enum.toString () returnerer samme verdi som Enum.name ().

7.2. Implementere et grensesnitt

De enum type i Java kan implementere grensesnitt. Selv om denne tilnærmingen ikke er så generisk som Enum API, grensesnitt hjelper oss med å generalisere.

La oss vurdere dette grensesnittet:

offentlig grensesnitt merket {String label (); }

For konsistens med Enum.name () metode, vår merkelapp() metoden har ikke en prefiks.

Og fordi den valueOfLabel () metoden er statisk, vi inkluderer det ikke i grensesnittet vårt.

Endelig kan vi implementere grensesnittet i vårt enum:

public enum Element implementerer merket {// ... @Override public String label () {return label; } // ...}

En fordel med denne tilnærmingen er at Merket grensesnitt kan brukes på alle klasser, ikke bare enum typer. I stedet for å stole på det generiske Enum API, har vi nå en mer kontekstspesifikk API.

8. Konklusjon

I denne artikkelen har vi utforsket mange funksjoner i Java Enum gjennomføring. Ved å legge til konstruktører, felt og metoder ser vi at enum kan gjøre mye mer enn bokstavelige konstanter.

Som alltid kan hele kildekoden for denne artikkelen finnes på GitHub.


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