Onveranderlijke objecten in Java

1. Overzicht

In deze zelfstudie leren we wat een object onveranderlijk maakt, hoe we onveranderlijkheid in Java kunnen bereiken en welke voordelen dit met zich meebrengt.

2. Wat is een onveranderlijk object?

Een onveranderlijk object is een object waarvan de interne toestand constant blijft nadat deze volledig is gemaakt.

Dit betekent dat de openbare API van een onveranderlijk object ons garandeert dat het zich gedurende zijn hele levensduur op dezelfde manier zal gedragen.

Als we de klas eens bekijken Draadkunnen we zien dat zelfs wanneer de API ons een veranderlijk gedrag lijkt te bieden met zijn vervangen methode, het origineel Draad verandert niet:

String name = "baeldung"; String newName = name.replace ("dung", "----"); assertEquals ("baeldung", naam); assertEquals ("bael ----", newName);

De API geeft ons alleen-lezen methoden, het mag nooit methoden bevatten die de interne status van het object wijzigen.

3. Het laatste Sleutelwoord in Java

Voordat we proberen onveranderlijkheid in Java te bereiken, moeten we het hebben over het laatste trefwoord.

In Java, variabelen zijn standaard veranderlijk, wat betekent dat we de waarde die ze bevatten kunnen veranderen.

Door de laatste trefwoord bij het declareren van een variabele, laat de Java-compiler ons de waarde van die variabele niet wijzigen. In plaats daarvan rapporteert het een compileerfout:

final String name = "baeldung"; name = "bael ...";

Let daar op laatste verbiedt ons alleen om de referentie van de variabele te wijzigen, het beschermt ons niet tegen het wijzigen van de interne status van het object waarnaar het verwijst door de openbare API te gebruiken:

final List strings = nieuwe ArrayList (); assertEquals (0, strings.size ()); strings.add ("baeldung"); assertEquals (0, strings.size ());

De seconde assertEquals zal mislukken omdat het toevoegen van een element aan de lijst de grootte verandert, daarom is het geen onveranderlijk object.

4. Onveranderlijkheid in Java

Nu we weten hoe we wijzigingen in de inhoud van een variabele kunnen vermijden, kunnen we deze gebruiken om de API van onveranderlijke objecten te bouwen.

Het bouwen van de API van een onveranderlijk object vereist dat we garanderen dat de interne staat niet verandert, ongeacht hoe we de API gebruiken.

Een stap voorwaarts in de goede richting is te gebruiken laatste bij het declareren van zijn attributen:

klassengeld {privé dubbel eindbedrag; particuliere eindvaluta; // ...}

Merk op dat Java ons garandeert dat de waarde van bedrag verandert niet, dat is het geval met alle primitieve typevariabelen.

In ons voorbeeld zijn we echter alleen gegarandeerd dat de valuta zal niet veranderen, dus we moeten vertrouwen op de Valuta API om zichzelf te beschermen tegen veranderingen.

Meestal hebben we de attributen van een object nodig om aangepaste waarden te bevatten, en de plaats om de interne toestand van een onveranderlijk object te initialiseren, is de constructor ervan:

class Money {// ... public Money (dubbel bedrag, valuta valuta) {this.amount = bedrag; this.currency = valuta; } openbare valuta getCurrency () {retourvaluta; } openbare dubbele getAmount () {retourbedrag; }}

Zoals we eerder hebben gezegd, om te voldoen aan de vereisten van een onveranderlijke API, onze Geld class heeft alleen-lezen methoden.

Met behulp van de reflectie-API kunnen we onveranderlijkheid doorbreken en onveranderlijke objecten wijzigen. Reflectie is echter in strijd met de openbare API van onveranderlijk object en meestal moeten we dit vermijden.

5. Voordelen

Omdat de interne toestand van een onveranderlijk object constant blijft in de tijd, we kunnen het veilig delen met meerdere threads.

We kunnen het ook vrij gebruiken, en geen van de objecten die ernaar verwijzen zullen enig verschil merken, dat kunnen we wel zeggen onveranderlijke objecten zijn vrij van bijwerkingen.

6. Conclusie

Onveranderlijke objecten veranderen hun interne toestand niet na verloop van tijd, ze zijn draadveilig en vrij van bijwerkingen. Vanwege deze eigenschappen zijn onveranderlijke objecten ook bijzonder handig in omgevingen met meerdere threads.

Je kunt de voorbeelden vinden die in dit artikel worden gebruikt op GitHub.