logo

Com crear una classe immutable a Java?

A Java, la immutabilitat significa que un cop creat un objecte no es pot canviar el seu estat intern. Les classes immutables a Java ofereixen molts avantatges com ara una depuració fàcil de seguretat de fils i tot. En Java tots els classes d'embolcall (com Integer Boolean Byte Short) i la classe String és immutable. També podem crear la nostra pròpia classe immutable.

En aquest article aprendrem:



  • Què vol dir immutabilitat
  • Per què és útil
  • Com crear la nostra pròpia classe immutable
  • Per què és important la còpia profunda
  • Quines són les limitacions que tenen els tipus de registre Java

Què és una classe immutable?

Una classe immutable és una classe els objectes de la qual no es poden canviar un cop creats. Si fem alguna modificació es tradueix en un objecte nou. Aquest mètode s'utilitza en aplicacions concurrents.

Regles per crear una classe immutable

  • La classe s'ha de declarar com final de manera que no es poden crear classes infantils.
  • S'han de declarar els membres de les dades de la classe privat de manera que no es permet l'accés directe.
  • Els membres de dades de la classe s'han de declarar com final de manera que no podem canviar-ne el valor després de la creació de l'objecte.
  • Un constructor parametritzat hauria d'inicialitzar tots els camps realitzant a còpia profunda de manera que els membres de les dades no es poden modificar amb una referència d'objecte.
  • La còpia profunda d'objectes s'ha de realitzar als mètodes d'obtenció per retornar una còpia en lloc de tornar la referència real de l'objecte.

Nota : No hi hauria d'haver configuradors o, en termes més senzills, no hi hauria d'haver cap opció per canviar el valor de la variable d'instància.




Exemple: implementació de classe immutable

Estudiant.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;  } } 

En aquest exemple hem creat una classe final anomenada Estudiant. Té tres membres de dades finals, un constructor parametritzat i mètodes d'obtenció. Tingueu en compte que aquí no hi ha cap mètode de configuració. Tingueu en compte també que no cal que realitzem una còpia profunda o la clonació dels membres de dades dels tipus d'embolcall, ja que ja són immutables.



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

Fins i tot després de modificar el mapa original o retornat, l'estat intern de l'objecte Student es manté sense canvis. Això confirma el concepte d'immutabilitat.

Sortida:

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


Limitació del registre Java amb camps mutables

S'ha introduït Java 14 registre . Aquesta és una manera clara i concisa de definir classes com immutables:

record Student(String name int regNo Mapmetadades) {}


Però això només ofereix una immutabilitat superficial. Si el mapa es modifica externament, l'estat intern del registre canvia:

Mapamapa = nou HashMap<>();

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


Student s = new Student('ABC' 101 map);


// Canvia l'estat intern — NO és segur

comparet java

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

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

Nota : Utilitzeu el registre només si tots els camps són de tipus immutable com String int o altres registres.