مقابلة جافا: أسئلة حول OOP
1. ما هي خصائص جافا؟
إجابة:-
مفاهيم OOP:
- اتجاه الكائن
- ميراث
- التغليف
- تعدد الأشكال
- التجريد
-
عبر الأنظمة الأساسية: يمكن تشغيل برنامج Java على أي نظام أساسي دون أي تغييرات. بالطبع، يتطلب هذا تثبيت JVM (جهاز Java الظاهري).
-
الأداء العالي: يجعل برنامج التحويل البرمجي Just-In-Time (JIT) الأداء العالي ممكنًا. يقوم برنامج التحويل البرمجي JIT بتحويل الرمز الثانوي إلى رمز الجهاز ثم يبدأ JVM في التنفيذ.
- تعدد مؤشرات الترابط: يقوم JVM بإنشاء سلسلة تنفيذ تسمى
main thread
. يمكن للمبرمج إنشاء سلاسل رسائل متعددة عن طريق الاشتقاق من فئة Thread أو تنفيذRunnable
الواجهة.
2. ما هو الميراث؟
الوراثة تعني أنه يمكن لفئة واحدة أن ترث فئة أخرى (باستخدام الكلمة الأساسية الممتدة ). هذا يعني أنه يمكنك إعادة استخدام التعليمات البرمجية من الفصل الذي ورثته. تُعرف الفئة الحالية باسمsuperclass
والفئة التي تم إنشاؤها حديثًا هي subclass
. يقول الناس أيضًا استخدام المصطلحين الأصل و child
.
public class Animal {
private int age;
}
public class Dog extends Animal {
}
أين Animal
هو parent
و Dog
هو child
.
3. ما هو التغليف؟
غالبًا ما يتم طرح هذا السؤال في المقابلات الخاصة بوظائف مطوري Java. يقوم التغليف بإخفاء التنفيذ باستخدام معدّلات الوصول والحروف والمحددات. يتم ذلك لمنع الوصول الخارجي إلى أي مكان يعتقد المطورون أنه ضروري. مثال بسيط من الحياة الواقعية هو السيارة. ليس لدينا إمكانية الوصول المباشر إلى تشغيل المحرك. كل ما يتعين علينا القيام به هو وضع المفتاح في الإشعال وتشغيل المحرك. العمليات التي تتم تحت الغطاء ليست من شأننا. علاوة على ذلك، إذا قمنا بالتدخل في نشاط المحرك، فقد يؤدي ذلك إلى موقف غير متوقع، وربما يؤدي إلى تلف السيارة ويؤدي إلى ضرر جسدي. بالضبط نفس الشيء يحدث في البرمجة. تم وصف هذا جيدًا على ويكيبيديا . يوجد أيضًا مقال حول التغليف على CodeGym .4. ما هو تعدد الأشكال؟
تعدد الأشكال هو قدرة البرنامج على التعامل مع الكائنات ذات الواجهة نفسها بنفس الطريقة، دون معلومات حول نوع الكائن المحدد. وكما يقول المثل، "واجهة واحدة - العديد من التطبيقات". باستخدام تعدد الأشكال، يمكنك دمج واستخدام أنواع مختلفة من الكائنات بناءً على السلوكيات المشتركة. على سبيل المثال، لدينا فئة من الحيوانات تضم ذريتين: الكلب والقط. تتمتع فئة الحيوان العامة بسلوك مشترك بين الجميع، وهو القدرة على إصدار صوت. نستخدم إمكانات متعددة الأشكال عندما نحتاج إلى جمع كل ما يرث فئة الحيوان وتنفيذ طريقة "إصدار الصوت". وهنا كيف يبدو:List<Animal> animals = Arrays.asList(new Cat(), new Dog(), new Cat());
animals.forEach(animal -> animal.makeSound());
وبعبارة أخرى، تعدد الأشكال مفيد. وهذا ينطبق أيضًا على الأساليب متعددة الأشكال (المحملة بشكل زائد). كيفية استخدام تعدد الأشكال
أسئلة المقابلة حول بناء جملة جافا
5. ما هو المنشئ في جافا؟
يتمتع المنشئون بالخصائص التالية:- عند إنشاء كائن جديد، يستخدم البرنامج المنشئ المناسب لإنشائه.
- المنشئ يشبه الطريقة. تكمن سماته المميزة في عدم وجود قيمة إرجاع (بما في ذلك الفراغ) وأن اسمه هو نفس اسم الفئة.
- إذا لم يتم إنشاء مُنشئ بشكل صريح، فسيتم إنشاء مُنشئ فارغ تلقائيًا.
- يمكن تجاوز المنشئ.
- إذا قمت بتعريف مُنشئ بمعلمات ولكنك تحتاج أيضًا إلى مُنشئ بدون معلمات، فيجب عليك إنشائه بشكل منفصل، لأنه لن يتم إنشاؤه تلقائيًا.
6. أي الفئتين لا ترث الكائن؟
لا تنخدع بالأسئلة الخادعة، فلا توجد مثل هذه الفصول. ترث جميع الفئات فئة الكائن إما مباشرة أو من خلال أسلافها!7. ما هو المتغير المحلي؟
هذا سؤال شائع آخر للمقابلة لمطوري Java. المتغير المحلي هو متغير يتم تعريفه داخل الطريقة ويكون موجودًا طالما يتم تنفيذ الطريقة. بمجرد انتهاء التنفيذ، يتوقف المتغير المحلي عن الوجود. فيما يلي برنامج يستخدم متغيرًا محليًا يسمى helloMessage في الطريقة الرئيسية ():public static void main(String[] args) {
String helloMessage;
helloMessage = "Hello, World!";
System.out.println(helloMessage);
}
8. ما هو متغير المثيل؟
متغير المثيل هو متغير تم الإعلان عنه داخل الفصل. إنه موجود طالما أن الكائن موجود. على سبيل المثال، لدينا فئة Bee، والتي تحتوي على متغيرين — nectarLoad وmaxNectarLoad:public class Bee {
/**
* Current nectar load
*/
private double nectarLoad;
/**
* Maximum nectar that can the bee can collect.
*/
private double maxNectarLoad = 20.0;
...
}
9. ما هي معدّلات الوصول؟
معدّلات الوصول هي آلية لتخصيص الوصول إلى الفئات والأساليب والمتغيرات. توجد المعدلات التالية، وهي مدرجة حسب ترتيب زيادة الوصول:private
- يتم استخدام معدّل الوصول هذا في الأساليب والحقول والمنشئات. يقتصر الوصول على الفئة التي تم الإعلان عنها.package-private (default)
- هذا هو مستوى الوصول الافتراضي للفئات. يقتصر الوصول على الحزمة المحددة التي يتم فيها الإعلان عن فئة أو طريقة أو متغير أو مُنشئ.protected
- يوفر معدل الوصول هذا نفس مستوى الوصول كما هو الحالpackage-private
مع إضافة الوصول للفئات التي ترث فئة مع المعدلprotected
.public
- يُستخدم مستوى الوصول هذا أيضًا للفصول الدراسية. ويعني مستوى الوصول هذا أن هناك وصولاً كاملاً إلى التطبيق بأكمله.
10. ما هو أسلوب التجاوز؟
نحن نتجاوز الأساليب عندما يريد فصل فرعي تغيير سلوك فصله الأصلي. إذا أردنا أيضًا تنفيذ ما هو موجود في الطريقة الأصلية، فيمكننا استخدام super.methodName() في الطريقة الفرعية، والتي ستقوم بتنفيذ الطريقة الأصلية. يمكننا إضافة منطقنا الإضافي بعد ذلك. المتطلبات التي يجب مراعاتها:- يجب أن يكون توقيع الطريقة هو نفسه
- يجب أن تكون قيمة الإرجاع هي نفسها
11. ما هي توقيعات الطريقة؟
توقيع الطريقة هو مزيج من اسم الطريقة والوسائط التي تأخذها الطريقة. توقيع الطريقة هو المعرف الفريد للطريقة عند التحميل الزائد للطرق.12. ما هو أسلوب التحميل الزائد؟
التحميل الزائد للطريقة هو إحدى سمات تعدد الأشكال حيث نقوم بتغيير توقيع الطريقة لإنشاء طرق متعددة تؤدي نفس الإجراء:- نفس الاسم
- حجج مختلفة
- يمكن أن تكون هناك أنواع مختلفة من الإرجاع
ArrayList
الصنف add()
بشكل زائد، مما يسمح لنا بإضافة طرق مختلفة اعتمادًا على وسيطات الإدخال:
add(Object o)
- تضيف هذه الطريقة ببساطة كائنًاadd(int index, Object o)
- تضيف هذه الطريقة كائنًا إلى فهرس محددadd(Collection<Object> c)
- تضيف هذه الطريقة قائمة بالكائناتadd(int index, Collection<Object> c)
- تضيف هذه الطريقة قائمة بالكائنات بدءًا من فهرس محدد.
13. ما هي الواجهة؟
لا تدعم Java الميراث المتعدد. للتغلب على هذا القيد، تمت إضافة واجهات بالشكل الذي نعرفه ونحبه؛) لفترة طويلة، كانت الواجهات تحتوي على طرق فقط دون أي تنفيذ. في سياق هذه الإجابة، دعونا نتحدث عنهم. على سبيل المثال:
public interface Animal {
void makeSound();
void eat();
void sleep();
}
بعض التفاصيل تتبع من هذا:
- جميع الأساليب في الواجهة عامة ومجردة
- جميع المتغيرات نهائية عامة ثابتة
- لا ترث الفئات الواجهات (أي أننا لا نستخدم الكلمة الأساسية الممتدة). بدلاً من ذلك، تقوم الفئات بتنفيذها (على سبيل المثال، نستخدم الكلمة الأساسية للأدوات). علاوة على ذلك، يمكنك تنفيذ أي عدد تريده من الواجهات.
- يجب أن توفر الفئات التي تنفذ الواجهة تطبيقًا لجميع الأساليب الموجودة في الواجهة.
public class Cat implements Animal {
public void makeSound() {
// Method implementation
}
public void eat() {
// Implementation
}
public void sleep() {
// Implementation
}
}
14. ما هي الطريقة الافتراضية في الواجهة؟
الآن دعونا نتحدث عن الأساليب الافتراضية. لماذا هم؟ لمن هم؟ تمت إضافة هذه الطرق لخدمة "كلتا اليدين". ما الذي أتحدث عنه؟ حسنًا، من ناحية، كانت هناك حاجة لإضافة وظائف جديدة: lambdas وStream API. من ناحية أخرى، كان من الضروري الاحتفاظ بما تشتهر به Java - التوافق مع الإصدارات السابقة. وللقيام بذلك، احتاجت الواجهات إلى بعض الحلول الجديدة الجاهزة. هذه هي الطريقة التي جاءت إلينا الأساليب الافتراضية. الطريقة الافتراضية هي طريقة يتم تنفيذها في الواجهة، ويتم تمييزها بالكلمةdefault
الأساسية. على سبيل المثال، الطريقة المعروفة stream()
في Collection
الواجهة. صدقني، هذه الواجهة ليست بسيطة كما تبدو. أو أيضًا forEach()
الطريقة المشهورة بنفس القدر في Iterable
الواجهة. كما أنها لم تكن موجودة حتى تمت إضافة الطرق الافتراضية. بالمناسبة، يمكنك أيضًا القراءة عنها على CodeGym هنا
.
15. كيف إذن نرث طريقتين افتراضيتين متطابقتين؟
الإجابة السابقة حول ماهية الطريقة الافتراضية تطرح سؤالاً آخر. إذا كان بإمكانك تنفيذ الأساليب في الواجهات، فمن الناحية النظرية يمكنك تنفيذ واجهتين بنفس الطريقة. كيف نفعل ذلك؟ فيما يلي واجهتان مختلفتان بنفس الطريقة:interface A {
default void foo() {
System.out.println("Foo A");
}
}
interface B {
default void foo() {
System.out.println("Foo B");
}
}
ولدينا فئة تنفذ هاتين الواجهتين. ولكن كيف نختار طريقة معينة في الواجهة A أو B؟ البناء الخاص التالي يسمح بذلك: A.super.foo()
:
public class C implements A, B {
public void fooA() {
A.super.foo();
}
public void fooB() {
B.super.foo();
}
}
وبالتالي، fooA()
ستستخدم الطريقة foo()
الطريقة الافتراضية للواجهة A
، بينما fooB()
ستستخدم الطريقة foo()
طريقة الواجهة B
.
16. ما هي الأساليب والطبقات المجردة؟
في جافا،abstract
هي كلمة محجوزة. يتم استخدامه للدلالة على الطبقات والأساليب المجردة. أولا، نحتاج إلى تعريفات. الطريقة المجردة هي طريقة يتم الإعلان عنها باستخدام abstract
الكلمة الأساسية دون تطبيق في فئة مجردة. أي أن هذه طريقة كما في الواجهة، ولكن مع إضافة كلمة أساسية، على سبيل المثال:
public abstract void foo();
الفئة المجردة هي فئة تم تمييزها أيضًا بالكلمة abstract
الأساسية:
public abstract class A {
}
تحتوي الفئة المجردة على العديد من الميزات:
- لا يمكنك إنشاء كائن من فئة مجردة
- يمكن أن يكون لها أساليب مجردة
- وقد لا تحتوي أيضًا على طرق مجردة
17. ما الفرق بين String وStringBuilder وStringBuffer؟
String
يتم تخزين القيم في تجمع سلسلة ثابتة. بمجرد إنشاء سلسلة، تظهر في هذا التجمع. ولا يمكنك حذفه. على سبيل المثال:
String name = "book";
سيشير المتغير إلى تجمع السلاسل الثابتة. عند ضبط متغير الاسم على قيمة مختلفة، لدينا:
name = "pen";
يبدو تجمع السلسلة الثابتة كما يلي: وبعبارة أخرى، تظل كلا القيمتين هناك. المخزن المؤقت للسلسلة:
String
يتم تخزين القيم في مكدس. إذا تم تغيير قيمة، فإن القيمة الجديدة ستحل محل القيمة القديمة.String Buffer
متزامن وبالتالي فهو آمن للخيط.- نظرًا لسلامة الخيط، فإن أدائه ضعيف.
StringBuffer name = “book”;
بمجرد تغيير قيمة متغير الاسم، تتغير القيمة الموجودة في المكدس: StringBuilder هو نفسه تمامًا StringBuffer
، ولكنه ليس آمنًا لمؤشر الترابط. ونتيجة لذلك، فهو أسرع بشكل ملحوظ من StringBuffer
.
18. ما الفرق بين الفئة المجردة والواجهة؟
فئة مجردة:- تحتوي الفئات المجردة على مُنشئ افتراضي. يتم استدعاؤه في كل مرة يتم فيها إنشاء سليل للفئة المجردة.
- ويمكن أن تشمل كلاً من الأساليب المجردة والطرق غير المجردة. بشكل عام، لا يجب أن تحتوي الفئة المجردة على أساليب مجردة.
- يجب على الفصل الذي يرث فئة مجردة أن يطبق الأساليب المجردة فقط.
- يمكن أن تحتوي الفئة المجردة على متغيرات مثيل (راجع السؤال رقم 5).
- لا تحتوي الواجهة على مُنشئ ولا يمكن تهيئتها.
- يمكن إضافة الأساليب المجردة فقط (باستثناء الطرق الافتراضية).
- يجب على الفئات التي تنفذ الواجهة أن تنفذ كافة الأساليب (باستثناء الأساليب الافتراضية).
- يمكن أن تحتوي الواجهات على ثوابت فقط.
19. لماذا يتم الوصول إلى عنصر في المصفوفة O(1)؟
تم طرح هذا السؤال حرفيًا في مقابلتي الأخيرة. وكما تعلمت لاحقا، فإن الغرض من هذا السؤال هو معرفة كيف يفكر الشخص. ومن الواضح أن هناك قيمة عملية قليلة في هذه المعرفة. مجرد معرفة ذلك يكفي. أولاً، نحتاج إلى توضيح أن O(1) هو رمز للتعقيد الزمني لخوارزمية "الوقت الثابت". بمعنى آخر، يشير هذا التصنيف إلى أسرع وقت للتنفيذ. للإجابة على هذا السؤال، علينا أن نأخذ بعين الاعتبار ما نعرفه عن المصفوفات. لإنشاءint
مصفوفة يجب علينا كتابة ما يلي:
int[] intArray = new int[100];
ويمكن استخلاص عدة استنتاجات من هذا النحو:
- عندما يتم الإعلان عن مصفوفة، فإن نوعها معروف. إذا كان النوع معروفًا، فإن حجم كل خلية في المصفوفة يكون معروفًا.
- حجم المصفوفة بأكملها معروف.
فكيف نصل إلى O(1) عند الوصول إلى الكائنات في ArrayList؟
هذا السؤال يتبع مباشرة السؤال السابق. الحقيقة هي أنه عند العمل مع مصفوفة تحتوي على عناصر أولية، فإننا نعرف مسبقًا (في وقت الإنشاء) حجم نوع العنصر. ولكن ماذا نفعل إذا كان لدينا هذا النوع من التسلسل الهرمي للميراث وأردنا إنشاء مجموعة لعناصر من النوع A وإضافة تطبيقات مختلفة (B وC وD):List<A> list = new ArrayList();
list.add(new B());
list.add(new C());
list.add(new D());
list.add(new B());
وفي هذه الحالة كيف نحسب حجم كل خلية؟ بعد كل شيء، سيكون كل كائن مختلفًا، وربما مع حقول إضافية مختلفة. ما يجب القيام به؟ هنا يتم طرح السؤال بطريقة تهدف إلى إرباكك. نحن نعلم أن المجموعة لا تخزن الكائنات مباشرة. يقوم فقط بتخزين الإشارات إلى الكائنات. وجميع المراجع لها نفس الحجم، وهذا معروف. ونتيجة لذلك، فإننا نحسب العناوين هنا بنفس الطريقة كما في السؤال السابق.
21. التشغيل التلقائي والفتح
الخلفية التاريخية: يعد autoboxing وunboxing بعضًا من الابتكارات الرئيسية في JDK 5. Autoboxing هي عملية التحويل التلقائي من نوع بدائي إلى فئة مجمعة مقابلة. Unboxing هو عكس autoboxing تمامًا. إنها عملية تحويل فئة المجمع إلى فئة بدائية. ولكن إذا كانت قيمة الغلاف هيnull
, NullPointerException
فسيتم طرح a أثناء فتح العلبة.
البدائيون والأغلفة المقابلة لهم
بدائية | الطبقة المجمعة |
---|---|
منطقية | منطقية |
كثافة العمليات | عدد صحيح |
بايت | بايت |
شار | شخصية |
يطفو | يطفو |
طويل | طويل |
قصير | قصير |
مزدوج | مزدوج |
// يحدث التشغيل التلقائي:
-
عند تعيين بدائية لمرجع إلى فئة المجمع:
قبل جافا 5:
// Manual boxing (the way it was BEFORE Java 5). public void boxingBeforeJava5() { Boolean booleanBox = new Boolean(true); Integer intBox = new Integer(3); // And so on for other types } After Java 5: // Automatic boxing (the way it became in Java 5). public void boxingJava5() { Boolean booleanBox = true; Integer intBox = 3; // And so on for other types }
-
عندما يتم تمرير عنصر بدائي كوسيطة إلى طريقة تتوقع غلافًا:
public void exampleOfAutoboxing() { long age = 3; setAge(age); } public void setAge(Long age) { this.age = age; }
// يحدث فتح العلبة:
-
عندما نقوم بتعيين مثيل لفئة مجمعة لمتغير بدائي:
// BEFORE Java 5: int intValue = new Integer(4).intValue(); double doubleValue = new Double(2.3).doubleValue(); char c = new Character((char) 3).charValue(); boolean b = Boolean.TRUE.booleanValue(); // And after JDK 5: int intValue = new Integer(4); double doubleValue = new Double(2.3); char c = new Character((char) 3); boolean b = Boolean.TRUE;
-
أثناء العمليات الحسابية. تنطبق العمليات فقط على الأنواع البدائية، لذا يعد فك العلبة إلى الأنواع الأولية أمرًا ضروريًا.
// BEFORE Java 5: Integer integerBox1 = new Integer(1); Integer integerBox2 = new Integer(2); // A comparison used to require this: integerBox1.intValue() > integerBox2.intValue() // In Java 5 integerBox1 > integerBox2
-
عند تمرير مثيل لفئة مجمعة إلى طريقة تأخذ البدائية المقابلة:
public void exampleOfAutoboxing() { Long age = new Long(3); setAge(age); } public void setAge(long age) { this.age = age; }
22. ما هي الكلمة الرئيسية النهائية وأين يتم استخدامها؟
يمكن استخدام الكلمةfinal
الأساسية في المتغيرات والأساليب والفئات.
- لا يمكن تغيير قيمة المتغير النهائي بعد تهيئته.
- فصل أخير عقيم :) لا يمكن أن يكون له أطفال.
- لا يمكن تجاوز الطريقة النهائية بواسطة السليل.
المتغيرات النهائية
توفر لنا Java طريقتين للإعلان عن متغير وتعيين قيمة له:- يمكنك الإعلان عن متغير وتهيئته لاحقًا.
- يمكنك الإعلان عن متغير وتعيين قيمة على الفور.
public class FinalExample {
// A static final variable that is immediately initialized:
final static String FINAL_EXAMPLE_NAME = "I'm likely the final one";
// A final variable that is not initialized, but will only work if you
// initialize it in the constructor:
final long creationTime;
public FinalExample() {
this.creationTime = System.currentTimeMillis();
}
public static void main(String[] args) {
FinalExample finalExample = new FinalExample();
System.out.println(finalExample.creationTime);
// The final FinalExample.FINAL_EXAMPLE_NAME field cannot be accessed
// FinalExample.FINAL_EXAMPLE_NAME = "Not you're not!";
// The final Config.creationTime field cannot be accessed
// finalExample.creationTime = 1L;
}
}
هل يمكن اعتبار المتغير النهائي ثابتا؟
وبما أننا لا نستطيع تعيين قيم جديدة للمتغيرات النهائية، فيبدو أن هذه متغيرات ثابتة. لكن للوهلة الأولى فقط: إذا كان نوع بيانات المتغير هوimmutable
، فنعم، فهو ثابت. ولكن إذا كان نوع البيانات mutable
قابلاً للتغيير، فسيكون من الممكن استخدام الأساليب والمتغيرات لتغيير قيمة الكائن المشار إليه بواسطة متغير final
. وبسبب هذا، لا يمكن أن يسمى ثابتا. يوضح المثال التالي أن بعض المتغيرات النهائية هي في الواقع ثوابت، في حين أن بعضها الآخر ليس كذلك، حيث يمكن تغييرها.
public class FinalExample {
// Immutable final variables
final static String FINAL_EXAMPLE_NAME = "I'm likely the final one";
final static Integer FINAL_EXAMPLE_COUNT = 10;
// Mutable final variables
final List<String> addresses = new ArrayList();
final StringBuilder finalStringBuilder = new StringBuilder("Constant?");
}
المتغيرات النهائية المحلية
عندماfinal
يتم إنشاء متغير ضمن طريقة، فإنه يسمى متغير local final
:
public class FinalExample {
public static void main(String[] args) {
// You can do this
final int minAgeForDriveCar = 18;
// Or you can do this, in a for-each loop:
for (final String arg : args) {
System.out.println(arg);
}
}
}
يمكننا استخدام الكلمة الأساسية النهائية في حلقة for المحسنة، لأنه يتم إنشاء متغير جديد بعد كل تكرار للحلقة. ضع في اعتبارك أن هذا لا ينطبق على حلقة for العادية، لذلك سنحصل على خطأ أثناء الترجمة.
// The final local j variable cannot be assigned
for (final int i = 0; i < args.length; i ++) {
System.out.println(args[i]);
}
الطبقة النهائية
تم الإعلان عن فئةfinal
لا يمكن تمديدها. وبعبارة أكثر بساطة، لا يمكن لأي فئة أخرى أن ترثها. مثال ممتاز للفئة final
في JDK هو String. الخطوة الأولى لإنشاء فئة غير قابلة للتغيير هي وضع علامة عليها final
، وبالتالي منع توسيعها:
public final class FinalExample {
}
// Compilation error!
class WantsToInheritFinalClass extends FinalExample {
}
الطرق النهائية
عندما يتم وضع علامة نهائية على طريقة ما، فإنها تسمى طريقة نهائية (هذا منطقي، أليس كذلك؟). لا يمكن تجاوز الطريقة النهائية في فئة فرعية. بالمناسبة، تعتبر طرق الانتظار () وإخطار () الخاصة بفئة الكائن نهائية، لذلك ليس لدينا القدرة على تجاوزها.public class FinalExample {
public final String generateAddress() {
return "Some address";
}
}
class ChildOfFinalExample extends FinalExample {
// Compilation error!
@Override
public String generateAddress() {
return "My OWN Address";
}
}
كيف وأين يتم استخدام Final في Java
- استخدم الكلمة الأساسية الأخيرة لتحديد بعض الثوابت على مستوى الفصل الدراسي؛
- قم بإنشاء المتغيرات النهائية للكائنات التي لا تريد تغييرها. على سبيل المثال، الخصائص الخاصة بالكائن التي يمكننا استخدامها لأغراض التسجيل.
- إذا كنت لا ترغب في تمديد الفصل الدراسي، فقم بوضع علامة عليه كنهائي.
- إذا كنت بحاجة إلى إنشاء فئة غير قابلة للتغيير، فأنت بحاجة إلى جعلها نهائية.
- إذا كنت تريد ألا يتغير تنفيذ الطريقة في أحفادها، فقم بوضع علامة على الطريقة كـ
final
. هذا مهم جدًا للتأكد من أن التنفيذ لا يتغير.
23. ما هي الأنواع المتغيرة وغير القابلة للتغيير؟
متقلب
الكائنات القابلة للتغيير هي كائنات يمكن تغيير حالتها ومتغيراتها بعد إنشائها. تتضمن أمثلة الفئات القابلة للتغيير StringBuilder وStringBuffer. مثال:public class MutableExample {
private String address;
public MutableExample(String address) {
this.address = address;
}
public String getAddress() {
return address;
}
// This setter can change the name field
public void setAddress(String address) {
this.address = address;
}
public static void main(String[] args) {
MutableExample obj = new MutableExample("First address");
System.out.println(obj.getAddress());
// We are updating the name field, so this is a mutable object
obj.setAddress("Updated address");
System.out.println(obj.getAddress());
}
}
غير قابل للتغيير
الكائنات غير القابلة للتغيير هي كائنات لا يمكن تغيير حالتها ومتغيراتها بعد إنشاء الكائن. مفتاح رائع لـ HashMap، ألا تعتقد ذلك؟ :) على سبيل المثال، سلسلة، عدد صحيح، مزدوج، وما إلى ذلك. مثال:// We'll make this class final so no one can change it
public final class ImmutableExample {
private String address;
ImmutableExample(String address) {
this.address = address;
}
public String getAddress() {
return address;
}
// We remove the setter
public static void main(String[] args) {
ImmutableExample obj = new ImmutableExample("Old address");
System.out.println(obj.getAddress());
// There is no way to change this field, so it is an immutable object
// obj.setName("new address");
// System.out.println(obj.getName());
}
}
في الجزء التالي، سنتناول الأسئلة والأجوبة المتعلقة بالمجموعات. ملفي الشخصي على GitHub
أفضل 50 سؤالًا وإجابات لمقابلة العمل لـ Java Core. الجزء 2
GO TO FULL VERSION