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 bashJava
// 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:
Javaimport 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 Map
metadati) {}
Ma questo offre solo una superficiale immutabilità. Se la Mappa viene modificata esternamente lo stato interno del record cambia:
Mappa
mappa = 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