Hogyan lehet megváltoztathatatlan osztályt létrehozni Java-ban?

A Java-ban a megváltoztathatatlanság azt jelenti, hogy az objektum létrehozása után annak belső állapota nem változtatható meg. A Java megváltoztathatatlan osztályai számos előnnyel járnak, mint például a szálbiztonság egyszerű hibakeresése és minden. Java-ban az összes csomagoló osztályok (mint az Integer Boolean Byte Short), és a String osztály megváltoztathatatlan. Létrehozhatjuk saját változhatatlan osztályunkat is.

Ebben a cikkben a következőket fogjuk megtanulni:

  • Mit jelent a változhatatlanság
  • Miért hasznos
  • Hogyan hozzuk létre saját változhatatlan osztályunkat
  • Miért fontos a mélymásolás?
  • Milyen korlátai vannak a Java rekordtípusoknak?

Mi az a megváltoztathatatlan osztály?

A megváltoztathatatlan osztály olyan osztály, amelynek objektumai létrehozása után nem módosíthatók. Ha bármilyen módosítást végzünk, az új objektumot eredményez. Ezt a módszert párhuzamos alkalmazásokban használják.

A megváltoztathatatlan osztály létrehozásának szabályai

  • Az osztályt a következővel kell megadni végső hogy ne lehessen gyermekosztályokat létrehozni.
  • Az osztály adattagjait deklarálni kell magán hogy a közvetlen hozzáférés ne legyen megengedett.
  • Az osztály adattagjait a következőként kell megadni végső hogy az objektum létrehozása után ne tudjuk megváltoztatni az értéküket.
  • A paraméterezett konstruktornak inicializálnia kell az összes olyan mezőt, amely végrehajtja a mély másolat hogy az adattagokat ne lehessen objektumhivatkozással módosítani.
  • Az objektumok mélymásolását a getter metódusokban kell végrehajtani a másolat visszaadásához, nem pedig a tényleges objektumhivatkozás visszaadásához.

Jegyzet : Ne legyenek beállítók, vagy egyszerűbben ne legyen lehetőség a példányváltozó értékének megváltoztatására.


Példa: Változatlan osztálymegvalósítás

Diák.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  ;      }   }   

Ebben a példában létrehoztunk egy utolsó osztályt, melynek neve Diák. Három végső adattagja van, egy paraméterezett konstruktor és getter metódus. Felhívjuk figyelmét, hogy itt nincs beállító módszer. Azt is vegye figyelembe, hogy nem kell mélymásolni vagy klónozni a burkolótípusok adattagjait, mivel ezek már megváltoztathatatlanok.

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

Az eredeti vagy visszaadott térkép módosítása után is változatlan marad a Student objektum belső állapota. Ez megerősíti a megváltoztathatatlanság fogalmát.

Kimenet:

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


A Java rekord korlátozása változó mezőkkel

Bemutatták a Java 14-et rekord . Ez egy világos és tömör módja a megváltoztathatatlan osztályok meghatározásának:

rekord Diák(karakterlánc neve int regNo Map metaadatok) {}


De ez csak sekély változatlanságot kínál. Ha a Térképet kívülről módosítják, a rekord belső állapota megváltozik:

Térkép térkép = új HashMap <>();

map.put('1' 'első');


Diák s = new Student('ABC' 101 térkép);


// Megváltoztatja a belső állapotot — NEM biztonságos

map.put('2' 'másodperc');

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

Jegyzet : Csak akkor használja a rekordot, ha minden mező megváltoztathatatlan típusú, például String int vagy más rekordok.