Kako stvoriti nepromjenjivu klasu u Javi?

U Javi nepromjenjivost znači da kada je objekt kreiran, njegovo unutarnje stanje se ne može promijeniti. Nepromjenjive klase u Javi pružaju mnoge prednosti kao što je sigurnost niti, lako otklanjanje pogrešaka i sve ostalo. U Javi sve klase omotača (poput Integer Boolean Byte Short) i klasa String je nepromjenjiva. Možemo kreirati i vlastitu nepromjenjivu klasu.

U ovom članku ćemo naučiti:

  • Što znači nepromjenjivost
  • Zašto je to korisno
  • Kako stvoriti vlastitu nepromjenjivu klasu
  • Zašto je duboko kopiranje važno
  • Koja su ograničenja vrste Java zapisa

Što je nepromjenjiva klasa?

Nepromjenjiva klasa je klasa čiji se objekti ne mogu mijenjati nakon što su stvoreni. Ako napravimo bilo kakvu modifikaciju, to rezultira novim objektom. Ova se metoda koristi u istodobnim aplikacijama.

Pravila za stvaranje nepromjenjive klase

  • Klasa mora biti deklarirana kao konačni tako da se ne mogu kreirati podređene klase.
  • Članovi podataka u klasi moraju biti deklarirani privatni tako da izravan pristup nije dopušten.
  • Članovi podataka u klasi moraju biti deklarirani kao konačni tako da im ne možemo promijeniti vrijednost nakon stvaranja objekta.
  • Parametrizirani konstruktor treba inicijalizirati sva polja koja izvode a duboka kopija tako da se podatkovni članovi ne mogu mijenjati s referencom objekta.
  • Duboko kopiranje objekata trebalo bi se izvesti u getter metodama radi vraćanja kopije umjesto vraćanja stvarne reference objekta.

Bilješka : Ne bi trebalo postojati postavljači ili jednostavnije rečeno ne bi trebalo postojati opcija za promjenu vrijednosti varijable instance.


Primjer: Implementacija nepromjenjive klase

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

U ovom smo primjeru stvorili konačnu klasu pod nazivom Student. Ima tri konačna podatkovna člana, parametrizirani konstruktor i getter metode. Imajte na umu da ovdje ne postoji metoda postavljača. Također imajte na umu da ne moramo izvoditi dubinsko kopiranje ili kloniranje članova podataka tipova omotača jer su oni već nepromjenjivi.

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

Čak i nakon izmjene izvorne ili vraćene mape, unutarnje stanje studentskog objekta ostaje nepromijenjeno. Ovo potvrđuje koncept nepromjenjivosti.

Izlaz:

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


Ograničenje Java zapisa s promjenjivim poljima

Predstavljena Java 14 snimiti . Ovo je jasan i koncizan način za definiranje nepromjenjivih klasa:

zapis Student(String name int regNo Map metapodaci) {}


Ali ovo samo nudi plitku nepromjenjivost. Ako se Karta modificira izvana, unutarnje stanje zapisa se mijenja:

Karta karta = novi HashMap <>();

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


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


// Mijenja unutarnje stanje — NIJE sigurno

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

s.metadata().put('3' 'treći');

Bilješka : Koristite zapis samo ako su sva polja nepromjenjive vrste poput String int ili drugih zapisa.