كيفية إنشاء فئة غير قابلة للتغيير في جافا؟

تعني الثبات في Java أنه بمجرد إنشاء كائن، لا يمكن تغيير حالته الداخلية. توفر الفئات غير القابلة للتغيير في Java العديد من المزايا مثل أمان سلسلة المحادثات وسهولة تصحيح الأخطاء وجميعها. في جافا كل فئات المجمع (مثل عدد صحيح Boolean Byte Short) وفئة السلسلة غير قابلة للتغيير. يمكننا أيضًا إنشاء فئة غير قابلة للتغيير خاصة بنا.

في هذا المقال سوف نتعلم:

  • ماذا تعني الثبات
  • لماذا هو مفيد
  • كيفية إنشاء فئة غير قابلة للتغيير الخاصة بنا
  • لماذا النسخ العميق مهم
  • ما هي القيود التي تفرضها أنواع سجلات Java؟

ما هي الفئة غير القابلة للتغيير؟

الفئة غير القابلة للتغيير هي فئة لا يمكن تغيير كائناتها بمجرد إنشائها. إذا قمنا بأي تعديل فإنه يؤدي إلى كائن جديد. يتم استخدام هذه الطريقة في التطبيقات المتزامنة.

قواعد إنشاء فئة غير قابلة للتغيير

  • يجب الإعلان عن الفصل كـ أخير بحيث لا يمكن إنشاء فئات فرعية.
  • يجب الإعلان عن أعضاء البيانات في الفصل خاص بحيث لا يسمح بالوصول المباشر.
  • يجب الإعلان عن أعضاء البيانات في الفصل كـ أخير بحيث لا يمكننا تغيير قيمتها بعد إنشاء الكائن.
  • يجب أن يقوم المنشئ ذو المعلمات بتهيئة كافة الحقول التي تؤدي a نسخة عميقة بحيث لا يمكن تعديل أعضاء البيانات باستخدام مرجع كائن.
  • يجب إجراء النسخ العميق للكائنات باستخدام أساليب getter لإرجاع نسخة بدلاً من إرجاع مرجع الكائن الفعلي.

ملحوظة : يجب ألا يكون هناك أدوات ضبط أو بعبارات أبسط لا ينبغي أن يكون هناك خيار لتغيير قيمة متغير المثيل.


مثال: تنفيذ فئة غير قابلة للتغيير

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

في هذا المثال قمنا بإنشاء فئة نهائية تسمى طالب. يحتوي على ثلاثة أعضاء بيانات نهائية، أساليب مُنشئة ومُحصلة ذات معلمات. يرجى ملاحظة أنه لا توجد طريقة ضبط هنا. لاحظ أيضًا أننا لا نحتاج إلى إجراء نسخ عميق أو استنساخ لأعضاء البيانات من أنواع الأغلفة لأنها غير قابلة للتغيير بالفعل.

المهوسون جافا:

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

حتى بعد تعديل الخريطة الأصلية أو المعادة، تظل الحالة الداخلية لكائن الطالب دون تغيير. وهذا يؤكد مفهوم الثبات.

الإخراج:

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


حدود سجل Java مع الحقول القابلة للتغيير

تم تقديم جافا 14 سِجِلّ . هذه طريقة واضحة وموجزة لتعريف الفئات المشابهة غير القابلة للتغيير:

سجل الطالب (اسم السلسلة int regNo Map البيانات الوصفية) {}


لكن هذا لا يوفر سوى ثباتًا سطحيًا. إذا تم تعديل الخريطة خارجيًا، فستتغير الحالة الداخلية للسجل:

رسم خريطة Map = HashMap الجديد <>()؛

Map.put('1' 'الأول');


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


// يغير الحالة الداخلية - غير آمن

Map.put('2' 'الثانية');

s.metadata().put('3' 'الثالث');

ملحوظة : استخدم السجل فقط إذا كانت جميع الحقول من الأنواع غير القابلة للتغيير مثل String int أو السجلات الأخرى.