logo

Comment créer une classe immuable en Java ?

En Java, l'immuabilité signifie qu'une fois qu'un objet est créé, son état interne ne peut pas être modifié. Les classes immuables en Java offrent de nombreux avantages comme la sécurité des threads, le débogage facile et tout. En Java, tous les cours d'emballage (comme Integer Boolean Byte Short) et la classe String est immuable. Nous pouvons également créer notre propre classe immuable.

Dans cet article, nous allons apprendre :



  • Ce que signifie l'immuabilité
  • Pourquoi c'est utile
  • Comment créer notre propre classe immuable
  • Pourquoi la copie profonde est importante
  • Quelles sont les limitations des types d'enregistrement Java

Qu'est-ce qu'une classe immuable ?

Une classe immuable est une classe dont les objets ne peuvent pas être modifiés une fois créés. Si nous effectuons une modification, cela entraîne un nouvel objet. Cette méthode est utilisée dans les applications concurrentes.

Règles de création d'une classe immuable

  • La classe doit être déclarée comme final afin que les classes enfants ne puissent pas être créées.
  • Les données membres de la classe doivent être déclarées privé de sorte que l'accès direct n'est pas autorisé.
  • Les données membres de la classe doivent être déclarées comme final afin que nous ne puissions pas modifier leur valeur après la création de l'objet.
  • Un constructeur paramétré doit initialiser tous les champs effectuant une copie approfondie afin que les données membres ne puissent pas être modifiées avec une référence d'objet.
  • La copie approfondie des objets doit être effectuée dans les méthodes getter pour renvoyer une copie plutôt que de renvoyer la référence réelle de l'objet.

Note : Il ne devrait y avoir aucun paramètre ou, en termes plus simples, il ne devrait y avoir aucune option permettant de modifier la valeur de la variable d'instance.




négation mathématique discrète

Exemple : implémentation de classe immuable

Étudiant.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;  } } 

Dans cet exemple, nous avons créé une classe finale nommée Étudiant. Il comporte trois membres de données finaux, un constructeur paramétré et des méthodes getter. Veuillez noter qu'il n'y a pas de méthode de définition ici. Notez également que nous n'avons pas besoin d'effectuer une copie complète ou un clonage des données membres des types wrapper car elles sont déjà immuables.



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

Même après avoir modifié la carte originale ou renvoyée, l'état interne de l'objet Student reste inchangé. Cela confirme le concept d'immuabilité.

Sortir:

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


Limitation de l'enregistrement Java avec les champs mutables

Java 14 introduit enregistrer . Il s'agit d'une manière claire et concise de définir des classes immuables :

record Student (nom de chaîne int regNo Mapmétadonnées) {}


Mais cela n’offre qu’une immuabilité superficielle. Si la carte est modifiée en externe, l'état interne de l'enregistrement change :

Cartecarte = nouveau HashMap<>();

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


Étudiant s = nouvel étudiant (carte 'ABC' 101) ;


// Change l'état interne - PAS sûr

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

s.metadata().put('3' 'troisième');

Note : utilisez record uniquement si tous les champs sont de types immuables comme String int ou d'autres enregistrements.

debout