În Java, imuabilitatea înseamnă că odată ce un obiect este creat, starea sa internă nu poate fi schimbată. Clasele imuabile în Java oferă multe avantaje, cum ar fi siguranța firelor de depanare ușoară și toate. În Java toate clase de ambalare (cum ar fi Integer Boolean Byte Short) și clasa String este imuabilă. Ne putem crea și propria noastră clasă imuabilă.
În acest articol vom învăța:
- Ce înseamnă imuabilitate
- De ce este util
- Cum să ne creăm propria noastră clasă imuabilă
- De ce este importantă copierea profundă
- Care sunt limitările pe care le au tipurile de înregistrări Java
Ce este o clasă imuabilă?
O clasă imuabilă este o clasă ale cărei obiecte nu pot fi modificate odată create. Dacă facem vreo modificare, rezultă un obiect nou. Această metodă este utilizată în aplicații concurente.
Reguli pentru crearea unei clase imuabile
- Clasa trebuie declarată ca final astfel încât să nu poată fi create clase de copii.
- Membrii datelor din clasă trebuie să fie declarați privat astfel încât să nu fie permis accesul direct.
- Membrii datelor din clasă trebuie să fie declarați ca final astfel încât să nu le putem schimba valoarea după crearea obiectului.
- Un constructor parametrizat ar trebui să inițializeze toate câmpurile efectuând a copie adâncă astfel încât membrii datelor să nu poată fi modificați cu o referință la obiect.
- Copierea profundă a obiectelor ar trebui să fie efectuată în metodele getter pentru a returna o copie, mai degrabă decât a returna referința obiectului real.
Nota : Nu ar trebui să existe setări sau, în termeni mai simpli, nu ar trebui să existe nicio opțiune de modificare a valorii variabilei de instanță.
Exemplu: implementarea clasei imuabile
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; } }
În acest exemplu, am creat o clasă finală numită Student. Are trei membri de date finali, un constructor parametrizat și metode getter. Vă rugăm să rețineți că aici nu există o metodă de setare. De asemenea, rețineți că nu este nevoie să efectuăm copierea profundă sau clonarea membrilor de date ai tipurilor de wrapper, deoarece acestea sunt deja imuabile.
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()); } }
Chiar și după modificarea hărții originale sau returnate, starea internă a obiectului Student rămâne neschimbată. Aceasta confirmă conceptul de imuabilitate.
10 la sută din 60
Ieșire:
GFG
101
{1=first 2=second}
{1=first 2=second}
{1=first 2=second}
Limitarea înregistrării Java cu câmpuri mutabile
S-a introdus Java 14 înregistra . Acesta este un mod clar și concis de a defini clasele imuabile:
record Student(String name int regNo Map
metadate) {}
Dar aceasta oferă doar o imuabilitate superficială. Dacă Harta este modificată extern, starea internă a înregistrării se modifică:
Hartă
hartă = nou HashMap<>(); map.put('1' 'primul');
Student s = new Student(harta 'ABC' 101);
// Schimbă starea internă — NU este sigur
map.put('2' 'secunda');
prinde și încearcă javas.metadata().put('3' 'al treilea');
Nota : Folosiți înregistrarea numai dacă toate câmpurile sunt tipuri imuabile, cum ar fi String int sau alte înregistrări.