In Java betekent onveranderlijkheid dat zodra een object is gemaakt, de interne status ervan niet meer kan worden gewijzigd. Onveranderlijke klassen in Java bieden veel voordelen, zoals threadveiligheid, eenvoudig debuggen en zo. Op Java alle wrap klassen (zoals Integer Boolean Byte Short) en de klasse String is onveranderlijk. We kunnen ook onze eigen onveranderlijke klasse creëren.
In dit artikel gaan we leren:
- Wat onveranderlijkheid betekent
- Waarom het nuttig is
- Hoe we onze eigen onveranderlijke klasse kunnen creëren
- Waarom diep kopiëren belangrijk is
- Wat zijn de beperkingen die Java-recordtypen hebben?
Wat is een onveranderlijke klasse?
Een onveranderlijke klasse is een klasse waarvan de objecten niet meer kunnen worden gewijzigd nadat ze zijn gemaakt. Als we iets wijzigen, resulteert dit in een nieuw object. Deze methode wordt gebruikt in gelijktijdige toepassingen.
Regels voor het creëren van een onveranderlijke klasse
- De klasse moet worden gedeclareerd als definitief zodat er geen onderliggende klassen kunnen worden gemaakt.
- Gegevensleden in de klas moeten worden gedeclareerd privé zodat directe toegang niet is toegestaan.
- Gegevensleden in de klasse moeten worden gedeclareerd als definitief zodat we hun waarde niet kunnen veranderen na het maken van objecten.
- Een geparametriseerde constructor moet alle velden initialiseren die a uitvoeren diepe kopie zodat gegevensleden niet kunnen worden gewijzigd met een objectverwijzing.
- Deep Copy van objecten moet worden uitgevoerd in de getter-methoden om een kopie te retourneren in plaats van de daadwerkelijke objectreferentie terug te geven.
Opmerking : Er mogen geen setters zijn of, eenvoudiger gezegd, er mag geen optie zijn om de waarde van de instantievariabele te wijzigen.
Java-tekenreeks naar int-conversie
Voorbeeld: implementatie van onveranderlijke klassen
Student.java
Java// Java Program to Create An Immutable Class import java.util.HashMap; import java.util.Map; // declare the class as final final class Student { // make fields private and final private final String name; private final int regNo; private final Map<String String> metadata; // initialize all fields via constructor public Student(String name int regNo Map<String String> metadata) { this.name = name; this.regNo = regNo; // deep copy of mutable object (Map) Map<String String> tempMap = new HashMap<>(); for (Map.Entry<String String> entry : metadata.entrySet()) { tempMap.put(entry.getKey() entry.getValue()); } this.metadata = tempMap; } // only provide getters (no setters) public String getName() { return name; } public int getRegNo() { return regNo; } // return deep copy to avoid exposing internal state public Map<String String> getMetadata() { Map<String String> tempMap = new HashMap<>(); for (Map.Entry<String String> entry : this.metadata.entrySet()) { tempMap.put(entry.getKey() entry.getValue()); } return tempMap; } }
In dit voorbeeld hebben we een laatste klasse gemaakt met de naam Student. Het heeft drie laatste gegevensleden, een geparametriseerde constructor en getter-methoden. Houd er rekening mee dat er hier geen setter-methode is. Houd er ook rekening mee dat we geen diepgaande kopieën of klonen van gegevensleden van wrappertypen hoeven uit te voeren, omdat deze al onveranderlijk zijn.
Geeks.java:
geschiedenis op JavaJava
import java.util.HashMap; import java.util.Map; public class Geeks { public static void main(String[] args) { // create a map and adding data Map<String String> map = new HashMap<>(); map.put('1' 'first'); map.put('2' 'second'); // create an immutable Student object Student s = new Student('GFG' 101 map); // accessing data System.out.println(s.getName()); System.out.println(s.getRegNo()); System.out.println(s.getMetadata()); // try to modify the original map map.put('3' 'third'); System.out.println(s.getMetadata()); // try to modify the map returned by getMetadata() s.getMetadata().put('4' 'fourth'); System.out.println(s.getMetadata()); } }
Zelfs na het wijzigen van de originele of geretourneerde kaart blijft de interne status van het Student-object ongewijzigd. Dit bevestigt het onveranderlijkheidsconcept.
Uitgang:
GFG
101
{1=first 2=second}
{1=first 2=second}
{1=first 2=second}
Beperking van Java-record met veranderlijke velden
Java 14 geïntroduceerd dossier . Dit is een duidelijke en beknopte manier om onveranderlijke klassen te definiëren:
sites zoals bedpage
record Student(Stringnaam int regNo Map
metagegevens) {}
Maar dit biedt slechts oppervlakkige onveranderlijkheid. Als de kaart extern wordt gewijzigd, verandert de interne status van het record:
Kaart
kaart = nieuwe HashMap<>(); map.put('1' 'eerste');
java tostring
Student s = nieuwe student('ABC' 101 kaart);
// Verandert de interne status — NIET veilig
map.put('2' 'tweede');
s.metadata().put('3' 'derde');
Opmerking : Gebruik record alleen als alle velden onveranderlijke typen zijn, zoals String int of andere records.
gimp hoe u de selectie kunt opheffen