Inleiding tot onveranderlijken

1. Inleiding

In dit artikel laten we zien hoe u met de Immutables-bibliotheek kunt werken.

De bibliotheek bestaat uit annotaties en annotatieprocessors voor het genereren van en werken met serialiseerbare en aanpasbare onveranderlijke objecten.

2. Maven afhankelijkheden

Om Immutables in uw project te gebruiken, moet u de volgende afhankelijkheid toevoegen aan het afhankelijkheden sectie van uw pom.xml het dossier:

 org.immutables waarde 2.2.10 verstrekt 

Aangezien dit artefact niet vereist is tijdens runtime, is het raadzaam om het voorzien reikwijdte.

De nieuwste versie van de bibliotheek is hier te vinden.

3. Onveranderlijk

De bibliotheek genereert onveranderlijke objecten van abstracte typen: Koppel, Klasse, Annotatie.

De sleutel om dit te bereiken is het juiste gebruik van @ Waarde, onveranderlijk annotatie. Het genereert een onveranderlijke versie van een geannoteerd type en laat de naam voorafgaan door de Onveranderlijk trefwoord.

Als we proberen een onveranderlijke versie van de klasse te genereren met de naam 'X“, Zal het een klasse genereren met de naam "ImmutableX". Gegenereerde klassen zijn niet recursief-onveranderlijk, dus het is goed om dat in gedachten te houden.

En een korte opmerking - omdat Immutables annotatieverwerking gebruikt, moet u onthouden om annotatieverwerking in uw IDE in te schakelen.

3.1. Gebruik makend van @ Waarde, onveranderlijk Met Abstracte lessen en Interfaces

Laten we een eenvoudig maken abstract klasse Persoon bestaande uit twee abstract accessor-methoden die de te genereren velden vertegenwoordigen, en annoteer de klasse vervolgens met de @ Waarde, onveranderlijk annotatie:

@ Value.Immutable openbare abstracte klasse Persoon {abstracte String getName (); abstract Geheel getal getAge (); }

Nadat de annotatieverwerking is voltooid, kunnen we een gebruiksklare, nieuw gegenereerd Onveranderlijke Persoon klas in een doel / gegenereerde-bronnen directory:

@Generated ({"Immutables.generator", "Person"}) openbare laatste klasse ImmutablePerson breidt Persoon {private final String name; private finale Integer leeftijd; private ImmutablePerson (String naam, Integer leeftijd) {this.name = naam; this.age = leeftijd; } @Override String getName () {naam retourneren; } @Override Integer getAge () {terugkeer leeftijd; } // toString, hashcode, equals, copyOf en Builder weggelaten}

De gegenereerde klasse wordt geleverd met geïmplementeerd toString, hashcode, is gelijk aan methoden en met een stepbuilder Onveranderlijke Persoon. Bouwer. Merk op dat de gegenereerde constructor privaat toegang.

Om een ​​instantie van Onveranderlijke Persoon class, moeten we de builder- of statische methode gebruiken Onveranderlijke persoon. Kopie van, die een Onveranderlijke Persoon kopiëren van een Persoon voorwerp.

Als we een instantie willen bouwen met behulp van de builder, kunnen we eenvoudig coderen:

ImmutablePerson john = ImmutablePerson.builder () .age (42) .name ("John") .build ();

Gegenereerde klassen zijn onveranderlijk, wat betekent dat ze niet kunnen worden gewijzigd. Als u een reeds bestaand object wilt wijzigen, kunt u een van de "met X”Methoden, die een origineel object niet wijzigen, maar een nieuwe instantie met een gewijzigd veld creëren.

Laten we updaten John's leeftijd en creëer een nieuw john43 voorwerp:

ImmutablePerson john43 = john.withAge (43); 

In dat geval zijn de volgende beweringen waar:

assertThat (john) .isNotSameAs (john43);
assertThat (john.getAge ()). isEqualTo (42);

4. Aanvullende hulpprogramma's

Een dergelijke generatie van klassen zou niet erg nuttig zijn zonder deze aan te passen. De Immutables-bibliotheek wordt geleverd met een reeks aanvullende annotaties die kunnen worden gebruikt om aan te passen @ Waarde, onveranderlijk‘S output. Raadpleeg de documentatie van Immutables om ze allemaal te zien.

4.1. De @ Waarde.Parameter Annotatie

De @ Waarde.Parameter annotatie kan worden gebruikt voor het specificeren van velden, waarvoor constructormethode moet worden gegenereerd.

Als u uw klas als volgt annoteert:

@ Value.Immutable openbare abstracte klasse Persoon {@ Value.Parameter abstract String getName (); @ Value.Parameter abstract Geheel getal getAge (); }

Het is mogelijk om het op de volgende manier te instantiëren:

ImmutablePerson.of ("John", 42);

4.2. De @ Waarde.Standaard Annotatie

De @ Waarde.Standaard annotatie stelt u in staat een standaardwaarde op te geven die moet worden gebruikt als er geen beginwaarde wordt opgegeven. Om dit te doen, moet u een niet-abstracte accessormethode maken die een vaste waarde retourneert en deze annoteert met @ Waarde.Standaard:

@ Value.Immutable openbare abstracte klasse Persoon {abstracte String getName (); @ Value.Default Integer getAge () {return 42; }}

De volgende bewering zal waar zijn:

ImmutablePerson john = ImmutablePerson.builder () .name ("John") .build (); assertThat (john.getAge ()). isEqualTo (42);

4.3. De @ Waarde. Hulp Annotatie

De @ Waarde. Hulp annotatie kan worden gebruikt voor het annoteren van een eigenschap die wordt opgeslagen in de instantie van een object, maar wordt genegeerd door is gelijk aan, hashCode en toString implementaties.

Als u uw klas als volgt annoteert:

@ Value.Immutable openbare abstracte klasse Persoon {abstracte String getName (); abstract Geheel getal getAge (); @ Value.Auxiliary abstract String getAuxiliaryField (); }

De volgende beweringen zijn waar bij gebruik van de hulp veld:

ImmutablePerson john1 = ImmutablePerson.builder () .name ("John") .age (42) .auxiliaryField ("Value1") .build (); ImmutablePerson john2 = ImmutablePerson.builder () .name ("John") .age (42) .auxiliaryField ("Value2") .build (); 
assertThat (john1.equals (john2)). isTrue ();
assertThat (john1.toString ()). isEqualTo (john2.toString ()); 
assertThat (john1.hashCode ()). isEqualTo (john2.hashCode ());

4.4. De @ Value.Immutable (Prehash = True) Annotatie

Omdat onze gegenereerde klassen onveranderlijk zijn en nooit kunnen worden gewijzigd, hashCode resultaten blijven altijd hetzelfde en kunnen slechts één keer worden berekend tijdens de instantiatie van het object.

Als u uw klas als volgt annoteert:

@ Value.Immutable (prehash = true) openbare abstracte klasse Persoon {abstracte String getName (); abstract Geheel getal getAge (); }

Als je de gegenereerde klasse inspecteert, kun je dat zien hashcode waarde wordt nu vooraf berekend en opgeslagen in een veld:

@Generated ({"Immutables.generator", "Person"}) openbare laatste klasse ImmutablePerson breidt Persoon {private final String name; private finale Integer leeftijd; private finale int hashCode; private ImmutablePerson (String naam, Integer leeftijd) {this.name = naam; this.age = leeftijd; this.hashCode = computeHashCode (); } // gegenereerde methoden @Override public int hashCode () {return hashCode; }} 

De hashCode () methode retourneert een vooraf berekend hashcode gegenereerd toen het object werd gebouwd.

5. Conclusie

In deze korte tutorial hebben we de basiswerking van de Immutables-bibliotheek laten zien.

Alle broncode- en unit-tests in het artikel zijn te vinden in de GitHub-repository.