Kaip sukurti nepakeičiamą klasę „Java“?

Java nekintamumas reiškia, kad sukūrus objektą jo vidinė būsena negali būti pakeista. Nekintamos Java klasės suteikia daug privalumų, pvz., gijų sauga, lengvas derinimas ir viskas. Java programoje visi vyniojimo klasės (pavyzdžiui, Integer Boolean Byte Short) ir eilutės klasė yra nekintanti. Taip pat galime sukurti savo nekintamą klasę.

Šiame straipsnyje mes išmoksime:

  • Ką reiškia nekintamumas
  • Kodėl tai naudinga
  • Kaip sukurti savo nekintamą klasę
  • Kodėl gilus kopijavimas yra svarbus
  • Kokie yra Java įrašų tipų apribojimai

Kas yra nekintanti klasė?

Nekintamoji klasė yra klasė, kurios objektai negali būti pakeisti vieną kartą. Jei atliekame kokius nors pakeitimus, atsiranda naujas objektas. Šis metodas naudojamas lygiagrečiose programose.

Nekintamos klasės kūrimo taisyklės

  • Klasė turi būti deklaruota kaip galutinis kad nebūtų galima sukurti vaikų klasių.
  • Duomenų nariai klasėje turi būti deklaruoti privatus kad tiesioginė prieiga nebūtų leidžiama.
  • Duomenų nariai klasėje turi būti deklaruoti kaip galutinis kad sukūrę objektą negalėtume pakeisti jų vertės.
  • Konstruktorius su parametrais turėtų inicijuoti visus laukus, atliekančius a gili kopija kad duomenų nariai negalėtų būti modifikuojami naudojant objekto nuorodą.
  • Gilioji objektų kopija turėtų būti atliekama naudojant geterio metodus, norint grąžinti kopiją, o ne grąžinti tikrąją objekto nuorodą.

Pastaba : Neturėtų būti jokių nustatymų arba, paprasčiau tariant, neturėtų būti galimybės keisti egzemplioriaus kintamojo reikšmę.


Pavyzdys: nekintantis klasės įgyvendinimas

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

Šiame pavyzdyje sukūrėme galutinę klasę pavadinimu Studentas. Jame yra trys galutiniai duomenų nariai, parametrizuotas konstruktorius ir geterio metodai. Atkreipkite dėmesį, kad čia nėra nustatymo metodo. Taip pat atminkite, kad mums nereikia giliai kopijuoti arba klonuoti įpakavimo tipų duomenų narius, nes jie jau yra nekintami.

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

Net ir pakeitus pradinį arba grąžintą žemėlapį, Mokinio objekto vidinė būsena išlieka nepakitusi. Tai patvirtina nekintamumo sampratą.

Išvestis:

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


Java įrašo su kintamaisiais laukais apribojimas

Pristatyta Java 14 rekordas . Tai aiškus ir glaustas būdas apibrėžti nekintamas klases:

įrašas Studentas (Eilutės pavadinimas int regNr Žemėlapis metaduomenys) {}


Tačiau tai tik suteikia negilų nekintamumą. Jei žemėlapis modifikuojamas išoriškai, vidinė įrašo būsena pasikeičia:

Žemėlapis žemėlapis = naujas HashMap <>();

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


Student s = new Student ('ABC' 101 žemėlapis);


// Pakeičia vidinę būseną – NĖRA saugus

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

s.metadata().put('3' 'trečias');

Pastaba : naudokite įrašą, tik jei visi laukai yra nekintamų tipų, pvz., String int arba kiti įrašai.