{
  "assessmentTests": {
    "java_test": {
      "name": "اختبار Java",
      "desc": "30 سؤال حول قراءة الكود الفعلي — البحث عن ما يحدث عندما يعمل الكود بالفعل بدلاً من ما تتوقعه أن يحدث. مقارنة String باستخدام == بدلاً من .equals()، مخزن مؤقت Integer لـ autoboxing يجعل == تبدو أنها تعمل تحت 128 وتفشل بصمت فوقه، كتلة finally تلغي قيمة return دون أن يلاحظ أحد. اختبر نفسك عبر صيغة أساسية، overloading، المجموعات، الاستثناءات، والبرمجة المتزامنة.",
      "recommendation": "ملف ملخص مهاراتك في Java",
      "results": {
        "beginner": {
          "name": "مبتدئ",
          "desc": "تفهم الصيغة الأساسية والتنصيب والحلقات والشروط — الكود الذي تكتبه يعمل بشكل عام. الأخطاء التي أخطأت فيها تتمحور حول الحالات التي يتعارض فيها ما تتوقعه مع ما يفعله Java بالفعل: String مقارنات بـ ==، Integer autoboxing والتخزين المؤقت بين -128 و127، NullPointerExceptions التي تحدث بصمت لأن null مسموح به حيث لم تتوقع، كتل finally التي تلغي القيم. لا يتعلق الأمر بعدم فهمك للصيغة؛ الأمر يتعلق بفجوات في فهم كيفية تنفيذ أجزاء من الصيغة عمليًا.",
          "recommendation": "ركز على ثلاثة أشياء أولاً، بهذا الترتيب: لماذا == ينظر إلى الهوية بدلاً من المحتوى في String (و .equals() مطلوب بدلاً من ذلك)، كيفية عمل مخزن مؤقت Integer autoboxing وقيوده، وكيف تؤثر كتل finally على القيم المعاد إرجاعها. Effective Java والوثائق الرسمية لـ Java تغطي كلاً منها مع أمثلة قابلة للتشغيل."
        },
        "intermediate": {
          "name": "متوسط",
          "desc": "تكتب كودًا يعمل وتفهم أساسيات الكائنات والأنواع والمجموعات — HashMap أو ArrayList ليس بمثابة سحر أسود. الفجوة بيننا وبين المستقدم تتعلق بشكل أساسي بالتفاعلات: overload resolution عندما يكون هناك عدة طرق مطابقة بشكل جزئي، كيفية تخزين Generics في وقت التشغيل (المسح)، النوايا المرئية و Iterator.remove() بدلاً من list.remove() في حلقة، Stream laziness الذي يجعل العمليات غير المتوقعة لا تُنفذ على الإطلاق. هذه أنواع الأشياء التي تعمل بشكل صحيح في اختبار سريع وتظهر كأخطاء دقيقة فقط عندما تعمل مع أشخاص آخرين أو عندما يعود الكود بسلوك غير متوقع.",
          "recommendation": "ركز على كيفية تفاعل الأنواع والوراثة مع بعضها البعض بدلاً من كل شيء في عزلة: كيفية حل overload resolution عندما يكون هناك مطابقات متعددة، المسح والآثار المترتبة عليه على Generics في وقت التشغيل، ما يقوم به Iterator.remove() بشكل مختلف عن list.remove()، وعندما تُقيِّم Stream عمليات مقابل متى لا تفعل (lazy evaluation). المقالات المتعلقة بـ Effective Java و Java Concurrency حول Stream و Collections حيث ينقسم هذا الأشخاص الذين يعرفون الصيغة لكن لا يعرفون التنفيذ."
        },
        "advanced": {
          "name": "متقدم",
          "desc": "هذا هو المستوى الذي تعنيه معظم إعلانات الوظائف بـ \"Java قوي\". تقرأ فئة مع أنواع متوارثة ويمكنك التنبؤ بما سيحدث عند تمريرها إلى دالة متعددة الأشكال — بدلاً من مجرد محاولة تشغيله. تعرف متى ستستخدم synchronized و volatile بدلاً من التخمين، تفهم المقاطع والاستثناءات المرجعية (checked و unchecked)، وتعرف متى يكون LinkedList هو الخيار الصحيح بدلاً من ArrayList دائمًا. ما يفصل هذه الفئة عن الأعلى هو الجانب الدفاعي من البرمجة: معرفة متى تحتاج إلى بناء جملة try-with-resources، ما الذي بتحقق من صراحة ConcurrentModificationException، وكيفية تجنب مشاكل الذاكرة التي تحدث عندما لا تُغلق موارد.",
          "recommendation": "ادفع نفسك نحو الأجزاء التي تحمي البيانات التي يلمسها أشخاص آخرون أيضًا: الفرق بين synchronized و volatile وAtomicReference، متى تكون try-with-resources مطلوبة بدلاً من محاولة يدوية، وتسلسل استثناءات Java (Throwable و Exception و RuntimeException). استخدم Java Concurrency in Practice و Effective Java للغوص العميق في البرمجة المتزامنة والموارد والأمان كخطوة تالية."
        },
        "expert": {
          "name": "خبير",
          "desc": "حققت نتيجة في الأعلى من كل قسم — الصيغة الأساسية والأنواع والكائنات والوراثة والواجهات والجنريكس والمجموعات والتدفقات والاستثناءات والبرمجة المتزامنة والقفل وأمان الخيط والموارد والحسابات المرجعية. عمليًا، هذا يعني أنك يمكنك أن تأخذ كود من مدفق في طلب سحب وتقول بالضبط ما الذي سيتم طباعته وعندما سيحدث NullPointerException و ما إذا كان آمن للخيوط — وليس فقط ما يجب أن يفعل الكود، وهي المهارة الأصعب والأكثر قيمة. في هذا المستوى، لغة الكود النقية نادراً ما تكون العامل المحدد؛ الحد الأقصى هو عادة تصميم الفئة أو عدم إغلاق الموارد أو سوء فهم في حول كيفية يعمل المقفل.",
          "recommendation": "العائدات موجودة الآن في الأمان والقابلية للتوسع والأداء: قراءة ملفات تعريف الخيط والذاكرة قبل افتراض أن الكود بطيء، معرفة متى يكون synchronized كافياً مقابل atomic أو غير متزامن بالكامل، ومتى ينسب مشكلة إلى خيط غير محرر (thread leak) مقابل تسرب ذاكرة. إذا كنت يتم فحصك لدور، اوصف خطأ concurrency الذي وجدته في الكود — race condition أو deadlock أو حالة من عدم الأمان — بدلاً من تسمية الميزات وحدها، حيث يوضح هذا التفكير."
        }
      },
      "questions": [
        {
          "question": "تنشئ كائنات String اثنتين: String a = new String(\"cat\"); String b = new String(\"cat\"); ماذا تُقيّم a == b؟",
          "options": [
            {
              "icon": "",
              "label": "true — حروف String الحرفية بنفس الأحرف تكون دائماً نفس الكائن"
            },
            {
              "icon": "",
              "label": "true — new String(...) يُعيد استخدام string pool، لذا النص المتطابق يشترك دائماً في كائن واحد"
            },
            {
              "icon": "",
              "label": "خطأ compilation — == لا يمكن استخدامه لمقارنة كائنات String"
            },
            {
              "icon": "",
              "label": "false — new String(...) يُخصص دائماً كائن جديد على الـ heap، لذا == يقارن مرجعين مختلفين حتى لو كان .equals(b) يعود true"
            }
          ]
        },
        {
          "question": "Integer x = 100; Integer y = 100; System.out.println(x == y); ثم Integer x2 = 200; Integer y2 = 200; System.out.println(x2 == y2); ماذا يطبع السطران؟",
          "options": [
            {
              "icon": "",
              "label": "true ثم true — كائنات Integer المُصندقة تلقائياً تُخزّن مؤقتاً دائماً بغض النظر عن القيمة"
            },
            {
              "icon": "",
              "label": "false ثم false — == على كائنات Integer هي دائماً مقارنة مرجعية، لذا القيم المتساوية لا تتطابق أبداً"
            },
            {
              "icon": "",
              "label": "true ثم false، لكن فقط لأن 200 يتجاوز سعة byte — حد التخزين المؤقت لا علاقة له بـ -128..127"
            },
            {
              "icon": "",
              "label": "true ثم false — قيم Integer المُصندقة تلقائياً من -128 إلى 127 تُخزّن مؤقتاً وتُشترك، لذا 100 يعيد استخدام نفس الكائن، لكن 200 يقع خارج النطاق المخزّن مؤقتاً ويُصندق إلى كائنين منفصلين"
            }
          ]
        },
        {
          "question": "int max = Integer.MAX_VALUE; System.out.println(max + 1); ماذا يحدث؟",
          "options": [
            {
              "icon": "",
              "label": "يرفع ArithmeticException لـ integer overflow"
            },
            {
              "icon": "",
              "label": "يطبع Integer.MAX_VALUE مرة أخرى، لأن Java تُثبّت عند الحد الأقصى للنوع"
            },
            {
              "icon": "",
              "label": "يطبع Integer.MIN_VALUE — حسابات int تلتف بصمت عند الفائض بدلاً من رفع استثناء"
            },
            {
              "icon": "",
              "label": "خطأ compilation — المترجم يكتشف الفائض مسبقاً"
            }
          ]
        },
        {
          "question": "System.out.println(0.1 + 0.2 == 0.3); ماذا يطبع هذا، ولماذا؟",
          "options": [
            {
              "icon": "",
              "label": "false — لا يمكن تمثيل 0.1 و 0.2 و 0.3 بدقة في floating point ثنائي، لذا يحمل المجموع خطأ تقريب يجعله غير مساوٍ لـ 0.3 بت لبت"
            },
            {
              "icon": "",
              "label": "true — Java تقرّب حسابات double إلى أقرب عدد عشري قابل للتمثيل قبل المقارنة"
            },
            {
              "icon": "",
              "label": "true — جمع اثنين من double يكون دائماً دقيقاً للقيم برقمين عشريين"
            },
            {
              "icon": "",
              "label": "يرفع استثناء، لأن == غير مُعرّفة لـ double في Java"
            }
          ]
        },
        {
          "question": "فئة تصرح بحقلي instance بدون مُهيّئ: int count; و Integer total; قبل تشغيل constructor، ما قيمهما الافتراضية؟",
          "options": [
            {
              "icon": "",
              "label": "كلاهما افتراضي إلى 0، لأن Integer يُصندق إلى int عند تهيئة الحقل"
            },
            {
              "icon": "",
              "label": "count هو 0 و total هو 0، مُصندق تلقائياً أول مرة يُقرأ"
            },
            {
              "icon": "",
              "label": "count هو 0 و total هو null — حقول primitive رقمية تُفترض للصفر، لكن حقل مرجع wrapper غير مُهيّأ يُفترض إلى null مثل أي مرجع كائن آخر"
            },
            {
              "icon": "",
              "label": "كلاهما افتراضي إلى null حتى يُسند صراحة، لأن Java لا تملك defaults رقمية ضمنية"
            }
          ]
        },
        {
          "question": "حلقة تعمل 1000 مرة، كل مرة تفعل result += \"x\"; على String result. ماذا يحدث بالفعل تحت الغطاء كل تكرار؟",
          "options": [
            {
              "icon": "",
              "label": "يتم تمديد مصفوفة الأحرف الداخلية للـ String الموجود في مكانها"
            },
            {
              "icon": "",
              "label": "Java تدمج concatenations تلقائياً وتُخصص كائن String واحد نهائي فقط"
            },
            {
              "icon": "",
              "label": "ينجمع إلى استدعاء StringBuilder.append() واحد مشترك عبر كل التكرارات 1000، بدون كائن إضافي مُخصص لكل تكرار"
            },
            {
              "icon": "",
              "label": "يُنشأ كائن String جديد تماماً و result يُعاد تعيينه للإشارة إليه — كائن String السابق يُُرفَّع، لأن String غير قابل للتغيير و += لا يمكن أن تعدّله في مكانه"
            }
          ]
        },
        {
          "question": "final List<String> names = new ArrayList<>(); أي من هذه صحيح؟",
          "options": [
            {
              "icon": "",
              "label": "names.add(\"Ana\") ينجح — final يمنع فقط تعيين مرجع names نفسه، لا بتعديل الكائن الذي يشير إليه"
            },
            {
              "icon": "",
              "label": "names.add(\"Ana\") خطأ compilation، لأن final يجعل القائمة نفسها غير قابلة للتعديل"
            },
            {
              "icon": "",
              "label": "القائمة آمنة للخيوط للكتابات المتزامنة لأنها صُرحت باستخدام final"
            },
            {
              "icon": "",
              "label": "final على متغير محلي لا يؤثر إذا لم يكن النوع أيضاً immutable"
            }
          ]
        },
        {
          "question": "int[] a = {1, 2, 3}; int[] b = {1, 2, 3}; System.out.println(a == b); System.out.println(Arrays.equals(a, b)); ماذا يطبع السطران؟",
          "options": [
            {
              "icon": "",
              "label": "false ثم true — == تقارن مراجع المصفوفة (كائنا مصفوفة مختلفان)، بينما Arrays.equals تقارن العناصر"
            },
            {
              "icon": "",
              "label": "true ثم true — المصفوفات برفع محتوى متطابق هي نفس الكائن في Java"
            },
            {
              "icon": "",
              "label": "false ثم false — Arrays.equals تعمل فقط مع مصفوفات الكائنات، لا مصفوفات int primitive"
            },
            {
              "icon": "",
              "label": "true ثم false — == على المصفوفات تقارن المحتوى، و Arrays.equals زائدة عن الحاجة"
            }
          ]
        },
        {
          "question": "void show(Object o) { print(\"Object\"); } void show(String s) { print(\"String\"); } Object ref = \"hello\"; show(ref); أي overload يعمل، ولماذا؟",
          "options": [
            {
              "icon": "",
              "label": "show(String) يعمل، لأن Java تفحص الفئة الفعلية runtime للكائن قبل اختيار overload"
            },
            {
              "icon": "",
              "label": "show(Object) يعمل — حل overload يُقرر في compile time باستخدام النوع المُعلّن للمتغير، لا النوع الفعلي runtime للكائن"
            },
            {
              "icon": "",
              "label": "خطأ compilation — Object لا يمكن أن تُمرّر حيث يوجد overload أكثر تحديداً"
            },
            {
              "icon": "",
              "label": "كلا الطريقتين يعملان، مرة واحدة لكل، لأن Java تحل overloads بمحاولة كل مطابقة"
            }
          ]
        },
        {
          "question": "فئة Base بـ static void greet() { print(\"Base\"); }. فئة Derived توسّع Base وأيضاً تصرح static void greet() { print(\"Derived\"); }. تكتب: Base ref = new Derived(); ref.greet(); ماذا يطبع؟",
          "options": [
            {
              "icon": "",
              "label": "Derived — static methods تُلغي مثل instance methods، متّبعة النوع الفعلي runtime للكائن"
            },
            {
              "icon": "",
              "label": "خطأ compilation — static methods لا يمكن استدعاؤها عبر instance reference"
            },
            {
              "icon": "",
              "label": "Base — static methods ليست polymorphic؛ استدعاء واحد عبر مرجع يُحل بواسطة النوع المُعلّن للمرجع في compile time، لا النوع الفعلي runtime"
            },
            {
              "icon": "",
              "label": "Base و Derived معاً، لأن الاستدعاء يُحل لكلا الإصدارات المخفي والمُخفي"
            }
          ]
        },
        {
          "question": "داخل method، تكتب int count = 0; ثم تحاول الإشارة إلى count من داخل lambda مُمررة لـ method آخر. ما الذي يجب أن يكون صحيحاً حول count لكي ينجح compilation؟",
          "options": [
            {
              "icon": "",
              "label": "count يجب أن يكون effectively final — لا يُعاد تعيينه أبداً بعد قيمته الأولية — لأن lambda تلتقط snapshot، لا live reference إلى متغير محلي قابل للتغيير"
            },
            {
              "icon": "",
              "label": "لا شيء — أي متغير محلي يمكن أن يُقرأ و يُعاد تعيينه بحرية من داخل lambda"
            },
            {
              "icon": "",
              "label": "count يجب أن يُصرح volatile حتى lambda دائماً ترى قيمته الأخيرة"
            },
            {
              "icon": "",
              "label": "count يجب أن يكون حقل، ليس متغير محلي — lambdas لا يمكن أن تلتقط locals على الإطلاق"
            }
          ]
        },
        {
          "question": "void rename(StringBuilder sb) { sb = new StringBuilder(\"new\"); } يُستدعى كـ StringBuilder original = new StringBuilder(\"old\"); rename(original); ماذا يكون original بعد الاستدعاء؟",
          "options": [
            {
              "icon": "",
              "label": "يصبح \"new\" — الكائنات تُمرّ بواسطة reference في Java، لذا تعيين المعامل يُغيّر متغير المستدعي أيضاً"
            },
            {
              "icon": "",
              "label": "يصبح \"new\" فقط لأنواع قابلة للتغيير مثل StringBuilder، لكن ليس لأنواع immutable"
            },
            {
              "icon": "",
              "label": "لا يزال \"old\" — Java تُمرّر reference نفسه by value، لذا تعيين المعامل داخل method يُعيد تعيين النسخة المحلية فقط من reference، تاركاً original المستدعي دون تغيير"
            },
            {
              "icon": "",
              "label": "يرفع runtime exception، لأن sb تُعاد تعيين داخل method"
            }
          ]
        },
        {
          "question": "فئة بـ static initializer block، و instance initializer block، و constructor، بهذا الترتيب في الـ source. تُنشئ كائنين من هذه الفئة متتاليين. بأي ترتيب تعمل؟",
          "options": [
            {
              "icon": "",
              "label": "static block يعمل بالضبط مرة واحدة، أول مرة تُحمّل الفئة؛ ثم لكل كائن، instance block يعمل ثم constructor body يعمل"
            },
            {
              "icon": "",
              "label": "الثلاثة يعملان طازجاً، بترتيب الـ source، لكل كائن منفصل"
            },
            {
              "icon": "",
              "label": "constructor يعمل أولاً لكل كائن، ثم instance block، ثم static block مرة واحدة في النهاية جداً"
            },
            {
              "icon": "",
              "label": "static block يعمل مرة واحدة لكل كائن، مباشرة قبل instance block"
            }
          ]
        },
        {
          "question": "فئة بـ void log(String s) و void log(String... args). تستدعي log(\"hi\"). أي واحدة تعمل؟",
          "options": [
            {
              "icon": "",
              "label": "log(String... args) — overloads varargs تُفضّل دائماً عندما يكون كلاهما قابل للتطبيق"
            },
            {
              "icon": "",
              "label": "خطأ compilation — الاستدعاء غامض بين overloads الاثنين"
            },
            {
              "icon": "",
              "label": "log(String s) — عندما fixed-arity overload يطابق بالضبط، Java تفضّل دائماً على varargs overload، يُستخدم فقط كملاذ أخير"
            },
            {
              "icon": "",
              "label": "أيهما صُرح أولاً في الـ source file يعمل"
            }
          ]
        },
        {
          "question": "السطر الأول في constructor يستدعي this(0); لتفويض عمل إلى constructor آخر في نفس الفئة. أين يُسمح للظهور؟",
          "options": [
            {
              "icon": "",
              "label": "في أي مكان داخل جسم constructor، طالما يعمل قبل إرجاع الكائن"
            },
            {
              "icon": "",
              "label": "فقط كأول جملة من constructor — this() (أو super()) يجب أن يكون الخط الأول، و constructor لا يمكن أن يستدعي كل من this() و super()"
            },
            {
              "icon": "",
              "label": "فقط كآخر جملة، بعد انتهاء تهيئة جميع الحقول"
            },
            {
              "icon": "",
              "label": "فقط في constructors مُعلّمة صراحة كمُفوّضة، باستخدام keyword delegate"
            }
          ]
        },
        {
          "question": "تحتاج قائمة سيتم إدراج عناصر في المقدمة بكثرة جداً، و random-access reads نادرة. أيهما الأنسب هندسياً، ولماذا؟",
          "options": [
            {
              "icon": "",
              "label": "ArrayList — مصفوفتها الداخلية المتجاورة تجعل كل عملية، بما في ذلك front-insertion، أسرع من بنية مرتبطة"
            },
            {
              "icon": "",
              "label": "يعملان بشكل متطابق، لأن كليهما ينفذ interface List بنفس ضمانات الوقت"
            },
            {
              "icon": "",
              "label": "LinkedList — إدراج في المقدمة هو O(1) لأنه يُعيد ربط عقدة فقط، بينما ArrayList يجب أن يزيح كل عنصر موجود موضعاً واحداً، مما يجعل front-insertion O(n)"
            },
            {
              "icon": "",
              "label": "LinkedList، لأنه يدعم random access بـ O(1) بينما ArrayList لا يدعمه"
            }
          ]
        },
        {
          "question": "تُدرج خمس entries إلى HashMap عادي بترتيب معين، ثم تكرر عليه بـ for-each loop. بأي ترتيب تخرج entries؟",
          "options": [
            {
              "icon": "",
              "label": "نفس ترتيب entries تُدرج فيه، لأن Java maps دائماً تحافظ على insertion order"
            },
            {
              "icon": "",
              "label": "لا ترتيب مضمون على الإطلاق — HashMap iteration order يعتمد على hash bucket placement، لا insertion order، و يمكن أن يتغير حتى بين runs؛ LinkedHashMap هو ما يحافظ على insertion order"
            },
            {
              "icon": "",
              "label": "مرتبة بـ key تلقائياً، بنفس طريقة TreeMap تتصرف"
            },
            {
              "icon": "",
              "label": "عكس insertion order، لأن HashMap داخلياً يستخدم stack"
            }
          ]
        },
        {
          "question": "كم null keys يمكن لـ java.util.HashMap عادي أن يحتفظ به في كل مرة، و كم null values؟",
          "options": [
            {
              "icon": "",
              "label": "لا null keys و لا null values مسموحة أبداً في أي تطبيق Map"
            },
            {
              "icon": "",
              "label": "null key واحد على الأكثر، و أي عدد من null values — HashMap يسمح بـ null key واحد، بخلاف Hashtable التي لا تسمح بأي"
            },
            {
              "icon": "",
              "label": "null keys غير محدود و null values غير محدودة، لأن null يُعامل مثل أي key آخر"
            },
            {
              "icon": "",
              "label": "null key واحد و null value واحد أقصى، كلاهما مُحدّد بـ واحد"
            }
          ]
        },
        {
          "question": "تكرر List بـ for-each loop و تستدعي list.remove(item) مباشرة على القائمة من داخل جسم الحلقة، على بعض العناصر لكن ليس كل العناصر. ماذا يحدث؟",
          "options": [
            {
              "icon": "",
              "label": "يعمل بشكل صحيح و يزيل بالضبط العناصر المقصودة"
            },
            {
              "icon": "",
              "label": "يُخطي صمتاً العنصر بعد المُزال، لكن ينتهي بخلاف ذلك بدون خطأ"
            },
            {
              "icon": "",
              "label": "يرفع IndexOutOfBoundsException مرة تصل الحلقة إلى الحجم القديم للقائمة"
            },
            {
              "icon": "",
              "label": "يرفع ConcurrentModificationException — تعديل بنية القائمة مباشرة بينما implicit iterator يمشي عليها يُكتشف و يُرفض؛ Iterator.remove() يجب أن يُستخدم بدلاً من ذلك"
            }
          ]
        },
        {
          "question": "في runtime، given List<String> list، ماذا يمكنك فعلاً أن تحدد عن معامل نوعه generic عبر reflection أو instanceof؟",
          "options": [
            {
              "icon": "",
              "label": "يمكنك استدعاء list.getElementType() لاسترجاع String.class في runtime"
            },
            {
              "icon": "",
              "label": "instanceof List<String> يُترجم و يتحقق بشكل صحيح من نوع العنصر"
            },
            {
              "icon": "",
              "label": "JVM يخزن معامل النوع كـ metadata مخفي يمكن الوصول إليه عبر list.getGenericType()"
            },
            {
              "icon": "",
              "label": "لا شيء — معلومات النوع generic تُمحى في compile time، لذا في runtime الكائن هو فقط List، و لا توجد طريقة لاسترجاع ما إذا كان مُعلّن List<String> أم List<Integer>"
            }
          ]
        },
        {
          "question": "switch (day) { case 1: case 2: print(\"Weekday\"); break; case 6: print(\"Saturday\"); case 7: print(\"Sunday\"); break; default: print(\"?\"); } إذا كان day هو 6، ماذا يطبع؟",
          "options": [
            {
              "icon": "",
              "label": "Saturday فقط — كل كتلة case في switch دائماً تتوقف بعد جملة طباعتها الخاصة"
            },
            {
              "icon": "",
              "label": "Sunday فقط — المطابقة تبدأ عند case 6 لكن فقط آخر case مُطابق قبل break ينفذ"
            },
            {
              "icon": "",
              "label": "لا شيء يطبع، لأن day 6 ليس لديه case مطابق مع break خاص به مباشرة تحته"
            },
            {
              "icon": "",
              "label": "Saturday ثم Sunday — case 6 ليس لديه break، لذا execution يقع عبر (fall through) إلى كود case التالي قبل ضرب break التالي"
            }
          ]
        },
        {
          "question": "فئة Product تحتاج إلى order \"طبيعي\" واحد واضح بـ price، بالإضافة إلى القدرة أيضاً على order بـ name أو بـ stock level في أماكن مختلفة في الـ codebase. أي تركيبة هي التصميم الصحيح؟",
          "options": [
            {
              "icon": "",
              "label": "طبّق Comparable<Product> ثلاث مرات منفصلة، واحد لكل ordering، و دع المستدعي يختار أي compareTo يعمل"
            },
            {
              "icon": "",
              "label": "طبّق Comparable<Product> للـ natural price ordering، و اكتب Comparator<Product> منفصل instances للـ name و stock-level orderings المستخدمة في أماكن أخرى"
            },
            {
              "icon": "",
              "label": "استخدم فقط Comparator لكل ordering، بما فيها price، لأن Comparable ليس له ميزة هنا"
            },
            {
              "icon": "",
              "label": "استخدم فقط Comparable بإضافة compareTo methods متعددة الأحمال، واحد لكل ordering"
            }
          ]
        },
        {
          "question": "method يستدعي new FileReader(path)، الذي يصرح throws IOException. IOException توسّع Exception، ليس RuntimeException. ماذا يجب عليك فعل لكي يُترجم؟",
          "options": [
            {
              "icon": "",
              "label": "لا شيء — المترجم يفرض هذا فقط للـ exceptions التي تتوسّع RuntimeException"
            },
            {
              "icon": "",
              "label": "إما catch IOException في try/catch أو صرّح throws IOException على method الخاص بك — checked exceptions يجب أن يُعالَج أو يُنقل صراحة، بخلاف RuntimeException unchecked subclasses"
            },
            {
              "icon": "",
              "label": "لفّ الاستدعاء في try/catch لـ RuntimeException، لأن IOException يكون unchecked تلقائياً في Java حديث"
            },
            {
              "icon": "",
              "label": "صرّح method static — static methods معفاة من handled checked exception"
            }
          ]
        },
        {
          "question": "try (Resource a = new Resource(\"A\"); Resource b = new Resource(\"B\")) { ... } يستخدم مورديْ يطبّقان AutoCloseable. إذا انتهت كتلة try بشكل طبيعي، بأي ترتيب يُغلقان؟",
          "options": [
            {
              "icon": "",
              "label": "A يُغلق أولاً، ثم B، مطابقاً ترتيب الإعلان"
            },
            {
              "icon": "",
              "label": "B يُغلق أولاً، ثم A — try-with-resources يُغلق موارد بترتيب عكسي لترتيب الإعلان"
            },
            {
              "icon": "",
              "label": "كلاهما يُغلق بشكل متزامن، لأن try-with-resources ينازل cleanup"
            },
            {
              "icon": "",
              "label": "فقط B يُغلق تلقائياً — A يجب أن يُغلق يدوياً في finally block"
            }
          ]
        },
        {
          "question": "int getValue() { try { return 1; } finally { return 2; } } ماذا يعيد استدعاء getValue()؟",
          "options": [
            {
              "icon": "",
              "label": "1 — قيمة return من try block مُستقرة بالفعل قبل finally يعمل، لذا finally لا يمكن أن تُغيّره"
            },
            {
              "icon": "",
              "label": "يرفع exception في runtime، لأن method لا يمكن أن يعيد من مكانين"
            },
            {
              "icon": "",
              "label": "2 — return statement داخل finally يُلغي و يستبدل أي return مُستمر بالفعل من try block، متجاهلاً القيمة 1 بالكامل"
            },
            {
              "icon": "",
              "label": "خطأ compilation — finally لا يُسمح أن يحتوي على return statement"
            }
          ]
        },
        {
          "question": "try { ... } catch (IOException e) { ... } catch (FileNotFoundException e) { ... }، و FileNotFoundException توسّع IOException. ماذا يحدث عند محاولة ترجمة هذا؟",
          "options": [
            {
              "icon": "",
              "label": "خطأ compilation — كتلة FileNotFoundException catch غير قابلة للوصول لأن IOException catch السابق الأعم يطابق بالفعل كل FileNotFoundException"
            },
            {
              "icon": "",
              "label": "يُترجم بشكل صحيح، و FileNotFoundException catch الأخص يعمل عندما يُرفع هذا النوع بالضبط"
            },
            {
              "icon": "",
              "label": "يُترجم بشكل صحيح، و كلا catch blocks يعملان بالترتيب لـ FileNotFoundException"
            },
            {
              "icon": "",
              "label": "جيد عند compile time لكن يرفع runtime error أول مرة FileNotFoundException يحدث فعلاً"
            }
          ]
        },
        {
          "question": "فئة بـ synchronized instance method process() و synchronized static method configure(). ماذا، بالضبط، تقفل كل واحدة؟",
          "options": [
            {
              "icon": "",
              "label": "process() يقفل monitor من instance محدد يُستدعى عليه، بينما configure() يقفل monitor من Class object نفسه — مشترك بكل instance"
            },
            {
              "icon": "",
              "label": "كلاهما يقفل lock عام واحد لـ JVM بالكامل، بغض النظر عن instance أو class"
            },
            {
              "icon": "",
              "label": "process() يقفل Class object، و configure() يقفل أي instance يستدعيه اتفاقاً"
            },
            {
              "icon": "",
              "label": "لا أحدهما يقفل شيئاً إلا إذا كان synchronized block أيضاً داخل method body"
            }
          ]
        },
        {
          "question": "حقل مُصرح volatile int counter = 0;، و multiple threads تشغّل counter++ عليه concurrently. هل volatile يمنع lost updates هنا؟",
          "options": [
            {
              "icon": "",
              "label": "نعم — volatile يجعل كل عملية على الحقل atomic، بما في ذلك increments"
            },
            {
              "icon": "",
              "label": "لا — volatile فقط يضمن أن reads ترى latest write عبر threads (visibility)؛ counter++ هو read-modify-write بـ multiple steps، و volatile لا يفعل شيئاً لجعل تلك الخطوات atomic"
            },
            {
              "icon": "",
              "label": "لا — volatile لا يفعل شيئاً الآن، استخدم synchronized"
            },
            {
              "icon": "",
              "label": "نعم، لكن فقط لـ int و long fields بالضبط، بسبب كيفية JVM تتعامل مع 64-bit values"
            }
          ]
        },
        {
          "question": "Interface A و interface B كل واحد يُصرح default method describe(). فئة تطبّق A و B و لا تُلغي describe() نفسها. ماذا يحدث؟",
          "options": [
            {
              "icon": "",
              "label": "المترجم يختار version A تلقائياً، لأنه مُدرج أولاً في implements clause"
            },
            {
              "icon": "",
              "label": "كلا versions يعملان، واحد بعد الآخر، عندما describe() يُستدعى"
            },
            {
              "icon": "",
              "label": "جيد عند compile time، لكن يرفع AmbiguousMethodException أول مرة describe() يُستدعى"
            },
            {
              "icon": "",
              "label": "خطأ compilation — عندما interface اثنتان تُساهمان نفس default method، implementing class يجب أن تُلغي نفسها لحل الـ ambiguity، لأن Java لن تخمن أيهما تقصد"
            }
          ]
        },
        {
          "question": "list.stream().filter(x -> x > 0).map(x -> x * 2); تُكتب لكن النتيجة لا تُسند أبداً لـ terminal operation مثل .collect() أو .forEach(). ماذا يحدث فعلاً عند تنفيذ هذا السطر؟",
          "options": [
            {
              "icon": "",
              "label": "لا يحدث شيء على الإطلاق لعناصر القائمة — filter و map هما lazy intermediate operations التي تبني وصف pipeline فقط؛ بدون terminal operation، لا يُنفّذ أي جزء من pipeline بالفعل"
            },
            {
              "icon": "",
              "label": "كل عنصر يُصفّى و يُحوّل فوراً، بالضبط كما لو terminal operation دُعي"
            },
            {
              "icon": "",
              "label": "فقط filter يعمل فوراً؛ map يُؤجّل حتى terminal operation يظهر"
            },
            {
              "icon": "",
              "label": "يرفع IllegalStateException، لأن stream pipeline يحتاج terminal operation لكي يُترجم"
            }
          ]
        }
      ],
      "optionOrderVersion": "0154f9576054ad6f"
    }
  }
}
