logo

Come creare una classe immutabile in Java?

In Java l'immutabilità significa che una volta creato un oggetto il suo stato interno non può essere modificato. Le classi immutabili in Java offrono molti vantaggi come il debug facile della sicurezza dei thread e tutto il resto. In Giava tutto il classi wrapper (come Integer Boolean Byte Short) e la classe String è immutabile. Possiamo anche creare la nostra classe immutabile.

In questo articolo impareremo:



  • Cosa significa immutabilità
  • Perché è utile
  • Come creare la nostra classe immutabile
  • Perché la copia approfondita è importante
  • Quali sono le limitazioni dei tipi di record Java

Cos'è una classe immutabile?

Una classe immutabile è una classe i cui oggetti non possono essere modificati una volta creati. Se apportiamo qualsiasi modifica, il risultato sarà un nuovo oggetto. Questo metodo viene utilizzato in applicazioni simultanee.

Regole per la creazione di una classe immutabile

  • La classe deve essere dichiarata come finale in modo che le classi figlie non possano essere create.
  • I membri dati nella classe devono essere dichiarati privato pertanto non è consentito l'accesso diretto.
  • I membri dati nella classe devono essere dichiarati come finale in modo che non possiamo modificare il loro valore dopo la creazione dell'oggetto.
  • Un costruttore parametrizzato dovrebbe inizializzare tutti i campi eseguendo a copia profonda in modo che i membri dati non possano essere modificati con un riferimento a un oggetto.
  • La copia approfondita degli oggetti dovrebbe essere eseguita nei metodi getter per restituire una copia anziché restituire il riferimento all'oggetto effettivo.

Nota : Non dovrebbero esserci setter o, in termini più semplici, non dovrebbe esserci alcuna opzione per modificare il valore della variabile di istanza.




Esempio: implementazione di una classe immutabile

Student.java

if e altro in bash
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 questo esempio abbiamo creato una classe finale denominata Studente. Ha tre membri dati finali, un costruttore parametrizzato e metodi getter. Tieni presente che non esiste un metodo setter qui. Tieni inoltre presente che non è necessario eseguire una copia approfondita o la clonazione dei membri dati dei tipi wrapper poiché sono già immutabili.



Geeks.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());   } } 

Anche dopo aver modificato la mappa originale o restituita, lo stato interno dell'oggetto Student rimane invariato. Ciò conferma il concetto di immutabilità.

Produzione:

GFG  
101
{1=first 2=second}
{1=first 2=second}
{1=first 2=second}


Limitazione del record Java con campi mutabili

Introdotto Java 14 documentazione . Questo è un modo chiaro e conciso per definire classi simili immutabili:

formattatore di stringhe

record Studente(String nome int regNo Mapmetadati) {}


Ma questo offre solo una superficiale immutabilità. Se la Mappa viene modificata esternamente lo stato interno del record cambia:

Mappamappa = nuova HashMap<>();

map.put('1' 'primo');


Studente s = new Student(mappa 'ABC' 101);


// Cambia lo stato interno: NON sicuro

map.put('2' 'secondo');

s.metadata().put('3' 'terzo');

Nota : utilizza il record solo se tutti i campi sono di tipo immutabile come String int o altri record.

esempio di nome utente