تعني الثبات في 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; } }
في هذا المثال قمنا بإنشاء فئة نهائية تسمى طالب. يحتوي على ثلاثة أعضاء بيانات نهائية، أساليب مُنشئة ومُحصلة ذات معلمات. يرجى ملاحظة أنه لا توجد طريقة ضبط هنا. لاحظ أيضًا أننا لا نحتاج إلى إجراء نسخ عميق أو استنساخ لأعضاء البيانات من أنواع الأغلفة لأنها غير قابلة للتغيير بالفعل.
المهوسون جافا:
Javaimport 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 أو السجلات الأخرى.