Waarden aan Java Enum koppelen

1. Inleiding

De Java opsomming type biedt een taalondersteunde manier om constante waarden te maken en te gebruiken. Door een eindige reeks waarden te definiëren, kan de opsomming is meer type-safe dan constante letterlijke variabelen zoals Draad of int.

Echter, opsomming waarden zijn vereist om geldige ID's te zijn, en we worden aangemoedigd om SCREAMING_SNAKE_CASE volgens afspraak te gebruiken.

Gezien die beperkingen, de opsomming waarde alleen is niet geschikt voor door mensen leesbare tekenreeksen of niet-tekenreekswaarden.

In deze tutorial gebruiken we de opsomming‘S functies als een Java-klasse om de gewenste waarden te koppelen.

2. Java gebruiken Enum als een klas

We maken vaak een opsomming als een eenvoudige lijst met waarden. Hier zijn bijvoorbeeld de eerste twee rijen van het periodiek systeem als een simpele opsomming:

openbare opsomming Element {H, HE, LI, BE, B, C, N, O, F, NE}

Met behulp van de bovenstaande syntaxis hebben we tien statische, laatste exemplaren van het opsomming genaamd Element. Hoewel dit erg efficiënt is, hebben we alleen de elementensymbolen vastgelegd. En hoewel de vorm in hoofdletters geschikt is voor Java-constanten, is het niet hoe we de symbolen normaal gesproken schrijven.

Bovendien missen we ook andere eigenschappen van de elementen van het periodiek systeem, zoals de naam en het atoomgewicht.

Hoewel de opsomming type heeft speciaal gedrag in Java, we kunnen constructors, velden en methoden toevoegen zoals we doen met andere klassen. Hierdoor kunnen we onze opsomming om de waarden op te nemen die we nodig hebben.

3. Een constructor en een laatste veld toevoegen

Laten we beginnen met het toevoegen van de elementnamen. We zetten de namen in een laatste variabele met behulp van een constructor:

openbare opsomming Element {H ("Waterstof"), HE ("Helium"), // ... NE ("Neon"); openbaar definitief String-label; private Element (String label) {this.label = label; }}

Allereerst merken we de speciale syntaxis op in de aangiftelijst. Dit is hoe een constructor wordt aangeroepen opsomming types. Hoewel het illegaal is om de nieuw operator voor een opsommingkunnen we constructorargumenten doorgeven in de declaratielijst.

Vervolgens declareren we een instantievariabele etiket. Er zijn een paar dingen om op te merken.

Ten eerste kozen we voor de etiket identifier in plaats van de naam. Hoewel het ledenveld naam beschikbaar is voor gebruik, laten we kiezen etiket om verwarring met het voorgedefinieerde te voorkomen Enum.name () methode.

Ten tweede, onze etiket veld is laatste. Terwijl velden van een opsomming hoeft niet te zijn laatste, in de meeste gevallen willen we niet dat onze labels veranderen. In de geest van opsomming waarden zijn constant, dit is logisch.

eindelijk, de etiket veld is openbaar. Daarom hebben we rechtstreeks toegang tot het label:

System.out.println (BE.label);

Aan de andere kant kan het veld zijn privaat, toegankelijk met een getLabel () methode. Om het kort te houden, zal dit artikel de stijl van het openbare veld blijven gebruiken.

4. Lokaliseren van Java Enum Waarden

Java biedt een valueOf (tekenreeks) methode voor iedereen opsomming types. We kunnen dus altijd een opsomming waarde op basis van de gedeclareerde naam:

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

Het kan echter zijn dat we een opsomming waarde ook door ons labelveld. Om dat te doen kunnen we een statisch methode:

openbare statische Element valueOfLabel (String label) {for (Element e: values ​​()) {if (e.label.equals (label)) {return e; }} retourneer null; }

De statische waardeOfLabel () methode herhaalt de Element waarden totdat het een overeenkomst vindt. Het keert terug nul als er geen overeenkomst wordt gevonden. Omgekeerd kan een uitzondering worden gegenereerd in plaats van terug te keren nul.

Laten we een snel voorbeeld bekijken met onze waardeOfLabel () methode:

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

5. Caching van de opzoekwaarden

We kunnen voorkomen dat de opsomming waarden met behulp van een Kaart om de labels te cachen. Om dit te doen, definiëren we een statische definitieve kaart en vul het in wanneer de klasse wordt geladen:

public enum Element {// ... enum values ​​private static final Map BY_LABEL = new HashMap (); statisch {for (Element e: values ​​()) {BY_LABEL.put (e.label, e); }} // ... velden, constructor, methoden openbaar statisch Element valueOfLabel (String label) {return BY_LABEL.get (label); }}

Omdat het in de cache is opgeslagen, wordt het opsomming waarden worden slechts één keer herhaald, en de waardeOfLabel () methode is vereenvoudigd.

Als alternatief kunnen we de cache lui construeren wanneer deze voor het eerst wordt geopend in het waardeOfLabel () methode. In dat geval moet de kaarttoegang worden gesynchroniseerd om gelijktijdigheidsproblemen te voorkomen.

6. Meerdere waarden koppelen

De Enum constructor kan meerdere waarden accepteren. Laten we ter illustratie het atoomnummer toevoegen als een int en het atoomgewicht als a vlotter:

openbare opsomming Element {H ("Waterstof", 1, 1.008f), HE ("Helium", 2, 4.0026f), // ... NE ("Neon", 10, 20.180f); privé statische definitieve kaart BY_LABEL = nieuwe HashMap (); privé statische definitieve kaart BY_ATOMIC_NUMBER = nieuwe HashMap (); privé statische definitieve kaart BY_ATOMIC_WEIGHT = nieuwe HashMap (); statisch {for (Element e: values ​​()) {BY_LABEL.put (e.label, e); BY_ATOMIC_NUMBER.put (e.atomicNumber, e); BY_ATOMIC_WEIGHT.put (e.atomicWeight, e); }} openbare laatste String-label; openbare finale int atomicNumber; openbare finale float atomicWeight; private Element (String label, int atomicNumber, float atomicWeight) {this.label = label; this.atomicNumber = atomicNumber; this.atomicWeight = atomicWeight; } openbare statische Element valueOfLabel (String label) {return BY_LABEL.get (label); } openbare statische Element valueOfAtomicNumber (int nummer) {return BY_ATOMIC_NUMBER.get (nummer); } openbare statische Element valueOfAtomicWeight (zwevend gewicht) {return BY_ATOMIC_WEIGHT.get (gewicht); }}

Op dezelfde manier kunnen we alle waarden die we willen toevoegen aan de opsomming, zoals de juiste hoofdlettersymbolen, "He", "Li" en "Be", bijvoorbeeld.

Bovendien kunnen we berekende waarden toevoegen aan onze opsomming door methoden toe te voegen om bewerkingen uit te voeren.

7. Besturen van de interface

Als resultaat van het toevoegen van velden en methoden aan ons opsomming, hebben we de openbare interface gewijzigd. Daarom is onze code, die gebruikmaakt van de core Enumnaam() en waarde van() methoden, zullen niet op de hoogte zijn van onze nieuwe velden.

De statischwaarde van() methode is al voor ons gedefinieerd door de Java-taal. Daarom kunnen we die van onszelf niet voorzien waarde van() implementatie.

Evenzo omdat de Enum.name () methode is laatste, we kunnen het ook niet opheffen.

Als gevolg hiervan is er geen praktische manier om onze extra velden te gebruiken met behulp van de standaard Enum API. Laten we in plaats daarvan eens kijken naar enkele verschillende manieren om onze velden bloot te leggen.

7.1. Overheersend toString ()

Overheersend toString () kan een alternatief zijn voor overschrijven naam():

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

Standaard, Enum.toString () geeft dezelfde waarde terug als Enum.name ().

7.2. Een interface implementeren

De opsomming type in Java kan interfaces implementeren. Hoewel deze benadering niet zo algemeen is als de Enum API, interfaces helpen ons om te generaliseren.

Laten we deze interface eens bekijken:

openbare interface Gelabeld {String label (); }

Voor consistentie met de Enum.name () methode, onze etiket() methode heeft geen krijgen voorvoegsel.

En, omdat de waardeOfLabel () methode is statisch, we nemen het niet op in onze interface.

Eindelijk kunnen we de interface implementeren in onze opsomming:

public enum Element implementeert Gelabeld {// ... @Override public String label () {return label; } // ...}

Een voordeel van deze aanpak is dat de Gelabeld interface kan op elke klasse worden toegepast, niet alleen opsomming types. In plaats van te vertrouwen op de generieke Enum API, we hebben nu een meer contextspecifieke API.

8. Conclusie

In dit artikel hebben we veel functies van Java onderzocht Enum implementatie. Door constructors, velden en methoden toe te voegen, zien we dat de opsomming kan veel meer dan letterlijke constanten.

Zoals altijd is de volledige broncode voor dit artikel te vinden op GitHub.