JavaRush /مدونة جافا /Random-AR /تحليل الأسئلة والأجوبة من المقابلات لمطور جافا. الجزء 16

تحليل الأسئلة والأجوبة من المقابلات لمطور جافا. الجزء 16

نشرت في المجموعة
مرحبا يا صديقي! كم من الوقت يستغرق لتصبح مطور؟ لقد سألت الكثير من الأشخاص المختلفين وسمعت الكثير من الإجابات المختلفة. بالنسبة لبعض الناس قد يكون شهرًا كافيًا، ولكن بالنسبة للآخرين حتى عام لن يكون كافيًا. لكنني أعلم على وجه اليقين أن أن تصبح مطورًا لـ Java هو طريق شائك وطويل، بغض النظر عن قدراتك الأولية. بعد كل شيء، ليست القدرة هي التي تهم العناد والعمل الجاد. تحليل الأسئلة والأجوبة من المقابلات لمطور جافا.  الجزء 16 - 1لذلك، نواصل اليوم تحليل أسئلة المقابلة الأكثر شيوعًا لمطوري Java. إن دراستها ستقربك تدريجيًا من هدفك العزيز. هيا بنا نبدأ!

17. أعط أمثلة على الاستخدام الناجح وغير الناجح للاختياري

لنفترض أن لدينا سلسلة معينة من القيم التي نمر من خلالها عبر الدفق، وفي النهاية نحصل على بعض الاختيارية نتيجة لذلك:
Optional<String> stringOptional = Stream.of("a", "ab", "abc", "abcd")
   .filter(str -> str.length() >= 3)
   .findAny();
نحن، كما هو متوقع، بحاجة إلى الحصول على القيمة من هذا الاختياري . مجرد استخدام get() يعد طريقة سيئة:
String result = stringOptional.get();
لكن من المفترض أن تحصل هذه الطريقة على القيمة من الاختياري وتعيدها إلينا؟ وهذا بالطبع صحيح، ولكن إذا كان له معنى. حسنًا، إذا كانت القيم الموجودة في الدفق مختلفة، وفي النهاية حصلنا على قيمة اختيارية فارغة ، فعندما نحاول أخذ قيمة منها باستخدام طريقة get() ، سيتم طرح ما يلي: تحليل الأسئلة والأجوبة من المقابلات لمطور جافا.  الجزء 16 - 2وهو ليس جيدًا. في هذه الحالة فمن الأفضل استخدام الإنشاءات التالية:
  1. String result = null;
    if (stringOptional.isPresent()) {
     stringOptional.get();
    }

    في هذه الحالة، نحن نتحقق لمعرفة ما إذا كان العنصر في اختياري أم لا . إذا لم يكن الأمر كذلك، فإن السلسلة الناتجة لها قيمتها القديمة.

  2. String result = stringOptional.orElse("default value");

    في هذه الحالة، نحدد بعض القيمة الافتراضية، والتي سيتم إعطاؤها للسلسلة الناتجة في حالة وجود خيار اختياري فارغ .

  3. String result = stringOptional.orElseThrow(() -> new CustomException());

    في هذه الحالة، نحن أنفسنا نطرح استثناءً عندما يكون الخيار الاختياري فارغًا .

يمكن أن يكون هذا مناسبًا في التطبيق، على سبيل المثال، عند استخدام طريقة Spring JPA - findById() ، والتي تُرجع قيمًا اختيارية . في هذه الحالة، باستخدام هذه الطريقة، نحاول أخذ القيمة، وإذا لم تكن موجودة، فإننا نرمي بعض استثناءات وقت التشغيل ، والتي تتم معالجتها على مستوى وحدة التحكم باستخدام ExceptionHandler وتحويلها إلى استجابة HTTP بالحالة 404 - لم يتم العثور عليها . تحليل الأسئلة والأجوبة من المقابلات لمطور جافا.  الجزء 16 - 3

18. هل من الممكن إعلان الطريقة الرئيسية نهائية؟

نعم، بالطبع ، لا شيء يمنعنا من إعلان الطريقة main() نهائية . لن ينتج المترجم أخطاء. لكن يجدر بنا أن نتذكر أن أي طريقة بعد إعلانها نهائية ستصبح الطريقة الأخيرة - ولن يتم تجاوزها. على الرغم من من سيعيد تعريف الرئيسي ؟؟؟ تحليل الأسئلة والأجوبة من المقابلات لمطور جافا.  الجزء 16 - 4

19. هل من الممكن استيراد نفس الحزمة/الفئة مرتين؟ ماذا يمكن أن تكون العواقب؟

نعم يمكنك ذلك. عواقب؟ سيكون لدينا بعض الواردات غير الضرورية التي ستعرضها Intelijj IDEA باللون الرمادي، أي. غير مستعمل. تحليل الأسئلة والأجوبة من المقابلات لمطور جافا.  الجزء 16 - 5تحليل الأسئلة والأجوبة من المقابلات لمطور جافا.  الجزء 16 - 6

20. ما هو الصب؟ متى يمكننا الحصول على ClassCastException؟

Casting، أو type casting ، هي عملية تحويل نوع بيانات واحد إلى نوع بيانات آخر: يدويًا (صب ضمني) أو تلقائيًا (صب نوع صريح). تحليل الأسئلة والأجوبة من المقابلات لمطور جافا.  الجزء 16 - 7يتم إجراء التحويل التلقائي بواسطة المترجم، ويتم إجراء التحويل اليدوي بواسطة المطور. يختلف نوع صب البدائيات والفئات إلى حد ما، لذلك سننظر فيها بشكل منفصل. الأنواع البدائية مثال على الصب الآلي للأنواع البدائية:
int value = 17;
double convertedValue = value;
كما ترون، ليست هناك حاجة إلى أي معالجة إضافية غير علامة = هنا. مثال على الصب اليدوي للأنواع البدائية:
double value = 17.89;
int convertedValue = (int)value;
في هذه الحالة، يمكننا ملاحظة عملية تحويل يدوية، والتي يتم تنفيذها باستخدام (int) ، حيث سيتم تجاهل الجزء بعد الفاصلة وستكون القيمة المحولة ذات قيمة - 17. اقرأ المزيد حول تحويل الأنواع البدائية في هذه المقالة . حسنًا، لننتقل الآن إلى الكائنات. الأنواع المرجعية بالنسبة للأنواع المرجعية، من الممكن النقل التلقائي للفئات التابعة إلى الفئات الأصلية. وهذا ما يسمى أيضا تعدد الأشكال . لنفترض أن لدينا فئة Lion ترث من فئة Cat . في هذه الحالة، سيبدو التحويل التلقائي كما يلي:
Cat cat = new Lion();
ولكن مع طاقم التمثيل الصريح ، كل شيء أكثر تعقيدًا إلى حد ما، لأنه لا توجد وظيفة لقطع الفائض، كما هو الحال مع البدائيين. وقم فقط بإجراء تحويل صريح للنموذج:
Lion lion= (Lion)new Cat();
سوف تحصل على خطأ: تحليل الأسئلة والأجوبة من المقابلات لمطور جافا.  الجزء 16 - 8في الواقع، يمكنك إضافة أساليب إلى الفئة المنحدرة من Lion والتي لم تكن موجودة في الفئة Cat في الأصل ، ثم محاولة الاتصال بها، لأن نوع الكائن الخاص بك سيصبح Lion . حسنا، ليس هناك منطق في هذا. لذلك، يكون تضييق النوع ممكنًا فقط عندما يكون الكائن الأصلي من النوع Lion ولكن تم تحويله لاحقًا إلى فئة أصل:
Lion lion = new Lion();
Cat cat = lion;
Lion newLion = (Lion)cat;
أيضًا، لمزيد من الموثوقية، يوصى باستخدام قالب تضييق للكائنات باستخدام مثيل الإنشاء :
if (cat instanceof Lion) {
 newLion = (Lion)new Cat();
}
اقرأ المزيد عن قوالب النوع المرجعي في هذه المقالة .

21. لماذا تستخدم الأطر الحديثة بشكل أساسي الاستثناءات غير المحددة فقط؟

أعتقد أن هذا كله لأن التعامل مع الاستثناءات المحددة لا يزال عبارة عن كود معكرونة يتكرر في كل مكان، ولكن ليس هناك حاجة إليه حقًا في جميع الحالات. تحليل الأسئلة والأجوبة من المقابلات لمطور جافا.  الجزء 16 - 9في مثل هذه الحالات، يكون من الأسهل إجراء المعالجة داخل الإطار، حتى لا يتم نقل ذلك مرة أخرى إلى أكتاف المطورين. نعم، بالطبع، قد تنشأ حالة طارئة، ولكن يمكن التعامل مع هذه الاستثناءات غير المحددة بطريقة أكثر ملاءمة، دون الحاجة إلى الاهتمام بالمعالجة في محاولة الالتقاط ودون تمريرها أكثر عبر الأساليب. يكفي فقط تحويل الاستثناء إلى بعض استجابات HTTP في ExceptionHandler .

22. ما هو الاستيراد الثابت؟

عند استخدام البيانات الثابتة (الطرق والمتغيرات)، لا يمكنك إنشاء الكائن نفسه، ولكن يمكنك القيام بذلك باسم الفئة، ولكن حتى في هذه الحالة نحتاج إلى رابط للفئة. كل شيء بسيط معه: تتم إضافته باستخدام الاستيراد العادي. ولكن ماذا لو ذهبنا لاستخدام طريقة ثابتة دون كتابة اسم الفئة، كما لو كانت طريقة ثابتة للفئة الحالية؟ هذا ممكن مع الاستيراد الثابت! في هذه الحالة، يجب أن نكتب استيرادًا ثابتًا ورابطًا لتلك الطريقة. مثل هذا، على سبيل المثال، طريقة ثابتة لفئة الرياضيات لحساب قيمة جيب التمام:
import static java.lang.Math.cos;
ونتيجة لذلك، يمكننا استخدام الأسلوب دون تحديد اسم الفئة:
double result = cos(60);
يمكننا أيضًا تحميل جميع الأساليب الثابتة للفئة مرة واحدة باستخدام الاستيراد الثابت:
import static java.lang.Math.*;
تحليل الأسئلة والأجوبة من المقابلات لمطور جافا.  الجزء 16 - 10

23. ما هي العلاقة بين أسلوبي hashCode() وequals()؟

وفقًا لـ Oracle ، القاعدة هي: إذا كان هناك كائنان متساويان (أي أن طريقة يساوي () ترجع صحيحًا )، فيجب أن يكون لهما نفس رمز التجزئة. وفي الوقت نفسه، لا تنس أن كائنين مختلفين يمكن أن يكون لهما نفس رمز التجزئة. لفهم سبب تجاوز يساوي () و hashCode () دائمًا في أزواج، ضع في اعتبارك الحالات التالية:
  1. يتم تجاوز كلتا الطريقتين.

    في هذه الحالة ، سيعود كائنان مختلفان لهما نفس الحالات الداخلية صحيحًا عندما يساوي () بينما سيعيد hashCode() نفس الرقم.

    اتضح أن كل شيء على ما يرام، لأنه يتم اتباع القاعدة.

  2. لا يتم تجاوز كلتا الطريقتين.

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

    ستعيد طريقة hashCode () أيضًا قيمًا مختلفة (على الأرجح) لأنها تنتج القيمة المحولة لعنوان موقع الذاكرة. لكن بالنسبة لنفس الكائن، ستكون هذه القيمة هي نفسها، تمامًا كما ستعود الدالةequal() ‎ في هذه الحالة صحيحة فقط عندما تشير المراجع إلى نفس الكائن.

    اتضح أنه في هذه الحالة كل شيء على ما يرام وتم استيفاء القاعدة.

  3. تم التجاوز يساوي() ، ولم يتم تجاوز hashCode() .

    في هذه الحالة، بالنسبة لكائنين مختلفين لهما نفس الحالات الداخلية، ستُرجع الدالة يساوي() القيمة true ، وسيُرجع التابع hashCode() قيمًا مختلفة (على الأرجح).

    وهذا انتهاك للقاعدة، لذلك لا ينصح بذلك.

  4. لم يتم تجاوز Equals() ، وتم تجاوز hashCode() .

    في هذه الحالة، بالنسبة لكائنين مختلفين لهما نفس الحالات الداخلية، ستُرجع الدالة يساوي() خطأ ، وسيُرجع التابع hashCode() نفس القيم.

    هناك انتهاك للقاعدة، وبالتالي فإن النهج غير صحيح.

كما ترون، لا يمكن تنفيذ القاعدة إلا عندما يتم تجاوز يساوي () و hashCode () أو لا يتم تجاوز كليهما على الإطلاق. اقرأ تحليل الأسئلة والأجوبة من المقابلات لمطور جافا.  الجزء 16 - 11المزيد عن يساوي () و hashCode () في هذه المقالة .

24. متى يتم استخدام فئتي BufferedInputStream وBufferedOutputStream؟

يتم استخدام InputStream لقراءة البيانات بايت بايت من بعض الموارد، ويتم استخدام OutputStream لكتابة البيانات بايت بايت. لكن عمليات البايت يمكن أن تكون غير مريحة للغاية وتتطلب معالجة إضافية (من أجل قراءة/كتابة النصوص بشكل طبيعي). في الواقع، لتبسيط سجلات البايت هذه، تم تقديم BufferedOutputStream ، وتم تقديم BufferedInputStream للقراءة . هذه الفئات ليست أكثر من مجرد مخازن مؤقتة تتراكم البيانات، مما يسمح لك بالعمل مع البيانات ليس بايت تلو الآخر، ولكن من خلال حزم البيانات بأكملها (المصفوفات). عند إنشائه، يأخذ BufferedInputStream في مُنشئه مثيلًا من نوع InputStream ، والذي تُقرأ منه البيانات:
BufferedInputStream bufferedInputStream = new BufferedInputStream(System.in);
byte[] arr = new byte[100];
bufferedInputStream.read(arr);
System.in هو كائن InputStream يقرأ البيانات من وحدة التحكم. أي أنه باستخدام كائن BufferedInputStream ، يمكننا قراءة البيانات من InputStream عن طريق كتابتها إلى المصفوفة التي تم تمريرها. يبدو أن هذا بمثابة غلاف لفئة InputStream . المصفوفة arr من هذا المثال هي المصفوفة التي تتلقى البيانات من BufferedInputStream . وهذا بدوره يقرأ البيانات من InputStream باستخدام صفيف آخر، والذي يبلغ حجمه افتراضيًا 2048 بايت. وينطبق الشيء نفسه على BufferedOutputStream : يجب تمرير مثيل من نوع OutputStream إلى المُنشئ ، حيث سنكتب البيانات في صفائف كاملة:
byte[] arr = "Hello world!!!".getBytes();
BufferedOutputStream bufferedInputStream = new BufferedOutputStream(System.out);
bufferedInputStream.write(arr);
bufferedInputStream.flush();
System.out هو كائن OutputStream الذي يكتب البيانات إلى وحدة التحكم. يرسل أسلوب Flush () البيانات من BufferedOutputStream إلى OutputStream ، مما يؤدي إلى مسح BufferedOutputStream في هذه العملية . وبدون هذه الطريقة لن يتم تسجيل أي شيء. وكما هو الحال في المثال السابق: arr هو المصفوفة التي يتم من خلالها كتابة البيانات إلى BufferedOutputStream . ومن هناك تتم كتابتها إلى OutputStream في مصفوفة مختلفة، والتي يبلغ حجمها افتراضيًا 512 بايت. اقرأ المزيد عن هاتين الفئتين في المقالة .

25. ما هو الفرق بين فئات java.util.Collection وjava.util.Collections؟

المجموعة عبارة عن واجهة تمثل رأس التسلسل الهرمي للمجموعة. يقدم فئات تسمح لك بإنشاء مجموعات كاملة من الكائنات واحتوائها وتعديلها. هناك العديد من الطرق المتوفرة لهذا الغرض، مثل add() و remove() و contains() وغيرها. الواجهات الرئيسية لفئة Collection :
  • المجموعة عبارة عن واجهة تصف مجموعة تحتوي على عناصر فريدة غير مرتبة (غير متكررة).

  • القائمة عبارة عن واجهة تصف بنية البيانات التي تخزن تسلسلًا مرتبًا للكائنات. تتلقى هذه الكائنات فهرسًا (رقمًا) خاصًا بها، والذي يمكنك من خلاله التفاعل معها: أخذها أو حذفها أو تغييرها أو استبدالها.

  • قائمة الانتظار هي واجهة تصف بنية البيانات مع تخزين العناصر في شكل قائمة انتظار تتبع القاعدة - FIFO - أول ما يدخل أولاً يخرج .

تحليل الأسئلة والأجوبة من المقابلات لمطور جافا.  الجزء 16 - 12اقرأ المزيد عن المجموعة . المجموعات هي فئة أدوات مساعدة توفر العديد من طرق الأداة المساعدة المختلفة. على سبيل المثال:
  • addAll(Collection<? super T> Collection, T...element) - يضيف العناصر التي تم تمريرها من النوع T إلى المجموعة .

  • نسخ (List<? super T> dest, List<? Extends T> src) - نسخ جميع العناصر من القائمة src إلى القائمة الموجودة في dest .

  • emptyList() - تقوم بإرجاع قائمة فارغة.

  • max(Collection<? Extends T> Collection, Comparator<? super T> comp) - يُرجع الحد الأقصى لعنصر مجموعة معينة وفقًا للترتيب المحدد بواسطة المقارنة المحددة.

  • unmodifiableList(List<? Extends T> list) - يُرجع تمثيلاً غير قابل للتعديل للقائمة التي تم تمريرها.

وهناك عدد كبير جدًا من هذه الطرق المختلفة والمريحة في المجموعات . تحليل الأسئلة والأجوبة من المقابلات لمطور جافا.  الجزء 16 - 13يمكن العثور على قائمة كاملة بهذه الطرق على موقع أوراكل الإلكتروني . ليس من قبيل الصدفة أنني قلت إنهم مرتاحون. بعد كل شيء، كلهم ​​​​ثابتة. أي أنك لا تحتاج إلى إنشاء كائن من هذه الفئة في كل مرة من أجل استدعاء الطريقة اللازمة عليه. كل ما تحتاجه هو إدخال اسم الفصل واستدعاء الطريقة المطلوبة عليه وتمرير جميع الوسائط المطلوبة. لتلخيص ذلك، المجموعة هي الواجهة الجذرية لإطار عمل المجموعات. المجموعات هي فئة مساعدة لمعالجة أكثر ملاءمة للكائنات التي تنتمي إلى نوع من بنية المجموعات. حسنا، هذا كل شيء لهذا اليوم. أتمنى لك كل خير!تحليل الأسئلة والأجوبة من المقابلات لمطور جافا.  الجزء 16 - 14
مواد أخرى في السلسلة:
تعليقات
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION