logo

Hoe maak je een onveranderlijke klasse in Java?

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 Java
Java
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 Mapmetagegevens) {}


Maar dit biedt slechts oppervlakkige onveranderlijkheid. Als de kaart extern wordt gewijzigd, verandert de interne status van het record:

Kaartkaart = 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