{
  "assessmentTests": {
    "java_test": {
      "name": "Java Test",
      "desc": "30 scenario na tanong tungkol sa core syntax, OOP mechanics, collections, generics, exceptions at concurrency — alamin kung tumutugma ang iyong Java sa ibig sabihin ng job posting na Java proficiency.",
      "recommendation": "Ang iyong Java skills profile",
      "results": {
        "beginner": {
          "name": "Nagsisimula pa lang",
          "desc": "Kaya mong sumulat ng gumaganang classes at methods, pero ang mga tanong na namiss mo ay nagkukumpol sa paligid ng identity at defaults sa halip na syntax — String == kumpara sa .equals, bakit hindi kailanman ginagamit ulit ng new String(\"x\") ang string pool, kung ano ang default ng numeric field kumpara sa wrapper field. Wala itong kinalaman sa pagiging mahina sa Java; ito ang mga partikular na rules na nagpapadapa sa mga taong natuto ng language sa trial-and-error sa halip na sa kung paano talaga gumagana ang references at primitives sa ilalim ng hood. Mahalaga ito sa trabaho dahil dito nangyayari na naka-compile, tumatakbo, at tahimik na mali ang code.",
          "recommendation": "Magsimula sa tatlong bagay, sa ganitong order: bakit inihahambing ng == sa dalawang String object ang references, hindi ang characters (at ang .equals ang halos laging gusto mo), paano tahimik na nagwi-wrap ang int overflow sa halip na mag-throw, at bakit ang uninitialized Integer field ay nagde-default sa null habang ang int field ay nagde-default sa 0. Sinasaklaw ng opisyal na Java tutorials ng Oracle at ng Baeldung ang tatlong ito na may runnable examples."
        },
        "intermediate": {
          "name": "Katamtaman",
          "desc": "Kaya mong hawakan nang komportable ang everyday application code — classes, collections, straightforward control flow — at hindi ka babagalan ng routine feature work. Ang gap sa pagitan nito at ng Advanced ay karamihan nasa nangyayari kapag nakikipag-interact ang mga rules ng Java sa concurrency at generics: isang static method na nire-resolve base sa declared type sa halip na sa object na inasahan mo, isang HashMap iteration order na tahimik mong inasahan, isang ConcurrentModificationException mula sa pag-alis ng item habang nasa gitna ng loop. Ang mga iyon ang uri ng bugs na nakakalusot sa mabilis na read-through at lalabas lang sa ilalim ng partikular na runtime condition.",
          "recommendation": "Tumutok sa kung paano iba ang static view ng compiler sa code mo kumpara sa kung ano talaga ang tumatakbo: overload resolution at static-method hiding base sa declared type sa halip na runtime type, bakit walang iteration-order guarantee ang HashMap, at bakit nagta-throw ng ConcurrentModificationException ang direktang pagbabago sa list habang ini-iterate ito. Tapos ang generics erasure, dahil ito ang nagpapadapa sa mga taong marunong na sa collections nang isa-isa."
        },
        "advanced": {
          "name": "Abante",
          "desc": "Ito ang level na tinutukoy ng karamihan ng job posting bilang \"strong Java.\" Binabasa mo ang isang class na may static blocks, instance blocks at maraming constructor at kaya mong hulaan ang eksaktong order ng pagtakbo nila, alam mo kung bakit tahimik na mada-discard ng finally block ang return value ng try block, at tumutungo ka sa try-with-resources sa halip na manual na finally-close dahil alam mo ang ordering guarantee na ibinibigay nito. Ang naghihiwalay sa band na ito mula sa pinakataas ay ang concurrent at interface-level na bahagi ng trabaho: ano talaga ang nili-lock ng synchronized, ano ang ginagarantiya at hindi ginagarantiya ng volatile, at paano nalulutas ang default-method conflicts.",
          "recommendation": "Tumungo sa mga bahaging nagpoprotekta sa code na ginagalaw rin ng ibang thread at ibang interface: ang pagkakaiba sa pagitan ng nili-lock ng synchronized instance method kumpara sa synchronized static method, bakit nagbibigay ang volatile ng visibility pero hindi ng atomicity para sa counter++, at paano ka pinipilit ng Java na lutasin nang manu-mano ang default-method diamond. Ang materyal ng Baeldung at ng Java Concurrency in Practice tungkol sa Java Memory Model ang natural na susunod na tigil para sa pareho."
        },
        "expert": {
          "name": "Eksperto",
          "desc": "Nag-score ka sa taas ng bawat section — core syntax at types, OOP mechanics at scope, collections at generics, at exceptions, concurrency at idioms. Praktikal, ibig sabihin nito ay puwede kang bigyan ng class ng isang estranghero at maipaliwanag mo kung bakit nangyayari ang isang compile error, runtime exception, o tahimik na maling value, hindi lang kung ano ang sinasabi ng syntax na dapat mangyari, na siyang mas mahirap at mas mahalagang kasanayan. Sa level na ito, bihira na ang language mismo ang limiting factor; ang limit ay karaniwang nasa concurrency design o sa hugis ng data sa ilalim nito.",
          "recommendation": "Nasa design at diagnosis na ngayon ang mga return: pagbabasa ng thread dump bago ipagpalagay na deadlock ang isang hang, pagpili sa pagitan ng synchronized, java.util.concurrent locks at atomics bilang tradeoff sa halip na default, at stream-pipeline design na sadyang nananatiling lazy sa halip na aksidente. Kung sini-screen ka para sa isang role, ilarawan ang isang concurrency bug tulad ng isang naligtaang happens-before edge o isang ConcurrentModificationException na nahanap mo sa production sa halip na pagngalanan ang mga Java feature — ipinapakita nito ang reasoning, hindi lang ang vocabulary."
        }
      },
      "questions": [
        {
          "question": "Gumagawa ka ng dalawang String objects: String a = new String(\"cat\"); String b = new String(\"cat\"); Ano ang resulta ng pag-evaluate ng a == b?",
          "options": [
            {
              "icon": "",
              "label": "true — ang mga String literal na may parehong characters ay palaging iisang object"
            },
            {
              "icon": "",
              "label": "true — ginagamit ulit ng new String(...) ang string pool, kaya ang magkaparehong text ay laging nagsha-share ng iisang object"
            },
            {
              "icon": "",
              "label": "Compile error — hindi puwedeng gamitin ang == para i-compare ang mga String object"
            },
            {
              "icon": "",
              "label": "false — laging naglalaan ang new String(...) ng bagong object sa heap, kaya ang == ay naghahambing ng dalawang magkaibang reference kahit na ang .equals(b) ay magbabalik ng true"
            }
          ]
        },
        {
          "question": "Integer x = 100; Integer y = 100; System.out.println(x == y); tapos Integer x2 = 200; Integer y2 = 200; System.out.println(x2 == y2); Ano ang ipi-print ng dalawang linya?",
          "options": [
            {
              "icon": "",
              "label": "true tapos true — laging naka-cache ang autoboxed Integer objects anuman ang value"
            },
            {
              "icon": "",
              "label": "false tapos false — ang == sa Integer objects ay laging reference comparison, kaya kailanman hindi magma-match ang magkaparehong values"
            },
            {
              "icon": "",
              "label": "true tapos false, pero dahil lang sa 200 na nag-o-overflow sa isang byte — hindi konektado ang cache boundary sa -128..127"
            },
            {
              "icon": "",
              "label": "true tapos false — ang mga autoboxed Integer value mula -128 hanggang 127 ay naka-cache at shared, kaya ang 100 ay gumagamit ulit ng iisang object, pero ang 200 ay lumalabas sa cache at nag-a-autobox sa dalawang magkahiwalay na object"
            }
          ]
        },
        {
          "question": "int max = Integer.MAX_VALUE; System.out.println(max + 1); Ano ang mangyayari?",
          "options": [
            {
              "icon": "",
              "label": "Nagta-throw ito ng ArithmeticException para sa integer overflow"
            },
            {
              "icon": "",
              "label": "Ipi-print nito ulit ang Integer.MAX_VALUE, dahil kino-clamp ng Java sa maximum ng type"
            },
            {
              "icon": "",
              "label": "Ipi-print nito ang Integer.MIN_VALUE — tahimik na nagwi-wrap around ang int arithmetic sa overflow sa halip na mag-throw"
            },
            {
              "icon": "",
              "label": "Compile error ito — nade-detect ng compiler ang overflow nang maaga"
            }
          ]
        },
        {
          "question": "System.out.println(0.1 + 0.2 == 0.3); Ano ang ipi-print nito, at bakit?",
          "options": [
            {
              "icon": "",
              "label": "false — hindi tumpak na maipapakita ang 0.1, 0.2 at 0.3 sa binary floating point, kaya may dalang rounding error ang kabuuan na hindi ito bit-for-bit equal sa 0.3"
            },
            {
              "icon": "",
              "label": "true — rino-round ng Java ang double arithmetic papunta sa pinakamalapit na representable decimal bago mag-compare"
            },
            {
              "icon": "",
              "label": "true — laging exact ang pagdagdag ng dalawang double para sa mga value na may dalawang decimal digit"
            },
            {
              "icon": "",
              "label": "Nagta-throw ito ng exception, dahil hindi defined ang == para sa double sa Java"
            }
          ]
        },
        {
          "question": "May class na nagde-declare ng dalawang instance field na walang initializer: int count; at Integer total; Bago tumakbo ang constructor, ano ang kanilang default values?",
          "options": [
            {
              "icon": "",
              "label": "Pareho silang nagde-default sa 0, dahil nag-a-autobox ang Integer papuntang int sa field initialization"
            },
            {
              "icon": "",
              "label": "0 ang count at 0 ang total, awtomatikong bino-box sa unang pagbasa nito"
            },
            {
              "icon": "",
              "label": "0 ang count at null ang total — nagde-default sa zero ang mga primitive numeric field, pero ang uninitialized wrapper reference field ay nagde-default sa null tulad ng ibang object reference"
            },
            {
              "icon": "",
              "label": "Pareho silang nagde-default sa null hanggang hindi explicit na naitalaga, dahil walang implicit numeric defaults ang Java"
            }
          ]
        },
        {
          "question": "May loop na tumatakbo ng 1000 beses, bawat pagkakataon ay ginagawa ang result += \"x\"; sa isang String result. Ano talaga ang nangyayari sa ilalim ng hood sa bawat iteration?",
          "options": [
            {
              "icon": "",
              "label": "Pinapahaba in-place ang internal character array ng existing String object"
            },
            {
              "icon": "",
              "label": "Awtomatikong bina-batch ng Java ang mga concatenation at isang final String object lang ang inilalaan"
            },
            {
              "icon": "",
              "label": "Nagko-compile ito papuntang iisang StringBuilder.append() call na shared sa lahat ng 1000 iteration, walang extra object na inilalaan kada iteration"
            },
            {
              "icon": "",
              "label": "May bagong String object na ginagawa at ire-reassign ang result para tumuro dito — dini-discard ang dating String object, dahil immutable ang String at hindi kayang baguhin ng += ito in-place"
            }
          ]
        },
        {
          "question": "final List<String> names = new ArrayList<>(); Alin sa mga ito ang totoo?",
          "options": [
            {
              "icon": "",
              "label": "Nagko-compile at gumagana nang maayos ang names.add(\"Ana\") — pinipigilan lang ng final ang pag-reassign sa names reference mismo, hindi ang pag-mutate sa object na tinuturo nito"
            },
            {
              "icon": "",
              "label": "Compile error ang names.add(\"Ana\"), dahil ginagawang unmodifiable ng final ang list mismo"
            },
            {
              "icon": "",
              "label": "Thread-safe ang list para sa concurrent writes dahil na-declare itong final"
            },
            {
              "icon": "",
              "label": "Walang epekto ang final sa isang local variable maliban kung na-declare rin na immutable ang type"
            }
          ]
        },
        {
          "question": "int[] a = {1, 2, 3}; int[] b = {1, 2, 3}; System.out.println(a == b); System.out.println(Arrays.equals(a, b)); Ano ang ipi-print ng dalawang linya?",
          "options": [
            {
              "icon": "",
              "label": "false tapos true — inihahambing ng == ang array references (dalawang magkaibang array object), habang inihahambing ng Arrays.equals ang mga elemento"
            },
            {
              "icon": "",
              "label": "true tapos true — ang mga array na may magkaparehong laman ay iisang object sa Java"
            },
            {
              "icon": "",
              "label": "false tapos false — gumagana lang ang Arrays.equals para sa object arrays, hindi para sa primitive int arrays"
            },
            {
              "icon": "",
              "label": "true tapos false — inihahambing ng == sa arrays ang laman, at redundant ang Arrays.equals"
            }
          ]
        },
        {
          "question": "void show(Object o) { print(\"Object\"); } void show(String s) { print(\"String\"); } Object ref = \"hello\"; show(ref); Aling overload ang tatakbo, at bakit?",
          "options": [
            {
              "icon": "",
              "label": "Tumatakbo ang show(String), dahil sinisiyasat ng Java ang aktwal na runtime class ng object bago pumili ng overload"
            },
            {
              "icon": "",
              "label": "Tumatakbo ang show(Object) — napagpapasyahan ang overload resolution sa compile time gamit ang declared type ng variable, hindi ang aktwal na runtime type ng object na tinutukoy nito"
            },
            {
              "icon": "",
              "label": "Compile error ito — hindi puwedeng ipasa ang Object kung saan may mas specific na overload"
            },
            {
              "icon": "",
              "label": "Parehong method ang tatakbo, isang beses bawat isa, dahil nire-resolve ng Java ang overloads sa pamamagitan ng pagsubok sa bawat match"
            }
          ]
        },
        {
          "question": "Ang class Base ay may static void greet() { print(\"Base\"); }. Ang class Derived ay extends Base at nagde-declare rin ng static void greet() { print(\"Derived\"); }. Isinusulat mo: Base ref = new Derived(); ref.greet(); Ano ang ipi-print?",
          "options": [
            {
              "icon": "",
              "label": "Derived — nagi-override ang static methods tulad ng instance methods, sumusunod sa aktwal na runtime type ng object"
            },
            {
              "icon": "",
              "label": "Compile error ito — hindi puwedeng tawagin ang static methods sa pamamagitan ng instance reference"
            },
            {
              "icon": "",
              "label": "Base — hindi polymorphic ang static methods; ang pagtawag ng isa sa pamamagitan ng reference ay nire-resolve base sa declared type ng reference sa compile time, hindi sa aktwal na type ng object"
            },
            {
              "icon": "",
              "label": "Parehong Base at Derived ang ipi-print, dahil nire-resolve ang tawag papunta sa hidden at hiding na version"
            }
          ]
        },
        {
          "question": "Sa loob ng isang method, isinusulat mo ang int count = 0; tapos sinusubukan mong i-reference ang count mula sa loob ng isang lambda na ipinasa sa ibang method. Ano ang dapat totoo tungkol sa count para makakompile ito?",
          "options": [
            {
              "icon": "",
              "label": "Dapat effectively final ang count — kailanman hindi na-reassign kahit saan matapos ang initial value nito — dahil kumukuha ang lambda ng snapshot, hindi ng live reference sa isang mutable local variable"
            },
            {
              "icon": "",
              "label": "Wala — anumang local variable ay malayang mababasa at mare-reassign mula sa loob ng isang lambda"
            },
            {
              "icon": "",
              "label": "Dapat i-declare na volatile ang count para laging makita ng lambda ang pinakahuling value nito"
            },
            {
              "icon": "",
              "label": "Dapat field ang count, hindi local variable — hindi talaga kayang kumuha ng locals ang lambdas"
            }
          ]
        },
        {
          "question": "Ang void rename(StringBuilder sb) { sb = new StringBuilder(\"new\"); } ay tinatawag bilang StringBuilder original = new StringBuilder(\"old\"); rename(original); Ano ang original pagkatapos ng tawag?",
          "options": [
            {
              "icon": "",
              "label": "Nagiging \"new\" — ipinapasa ang mga object by reference sa Java, kaya ang pag-reassign sa parameter ay nagbabago rin ng variable ng caller"
            },
            {
              "icon": "",
              "label": "Nagiging \"new\" lang para sa mutable types tulad ng StringBuilder, pero hindi para sa immutable types"
            },
            {
              "icon": "",
              "label": "Nananatiling \"old\" — ipinapasa ng Java ang reference mismo by value, kaya ang pag-reassign sa parameter sa loob ng method ay nagre-repoint lang sa local copy ng reference, hindi nagagalaw ang original ng caller"
            },
            {
              "icon": "",
              "label": "Nagta-throw ng runtime exception, dahil na-reassign ang sb sa loob ng method"
            }
          ]
        },
        {
          "question": "May class na may static initializer block, instance initializer block, at constructor, sa ganoong source order. Gumagawa ka ng dalawang object ng class na ito nang sunud-sunod. Anong order ang pagkakatakbo ng mga ito?",
          "options": [
            {
              "icon": "",
              "label": "Tatakbo ang static block nang isang beses lang, sa unang pag-load ng class; tapos para sa bawat object, tatakbo ang instance block at pagkatapos ang constructor body"
            },
            {
              "icon": "",
              "label": "Tatakbo ang lahat ng tatlo mula sa umpisa, sa source order, para sa bawat isang object na nagawa"
            },
            {
              "icon": "",
              "label": "Tatakbo muna ang constructor para sa bawat object, tapos ang instance block, tapos ang static block nang isang beses sa pinakadulo"
            },
            {
              "icon": "",
              "label": "Tatakbo ang static block nang isang beses kada object, mismong bago ang instance block"
            }
          ]
        },
        {
          "question": "May class na may void log(String s) at void log(String... args). Tinatawag mo ang log(\"hi\"). Alin ang tatakbo?",
          "options": [
            {
              "icon": "",
              "label": "log(String... args) — laging preferred ang varargs overloads kapag applicable ang pareho"
            },
            {
              "icon": "",
              "label": "Compile error ito — ambiguous ang tawag sa pagitan ng dalawang overload"
            },
            {
              "icon": "",
              "label": "log(String s) — kapag eksaktong tumugma ang isang fixed-arity overload, laging pinipili ito ng Java kaysa sa varargs overload, na ginagamit lang bilang last resort"
            },
            {
              "icon": "",
              "label": "Ang unang na-declare sa source file ang tatakbo"
            }
          ]
        },
        {
          "question": "Ang unang linya ng isang constructor ay tumatawag ng this(0); para i-delegate sa ibang constructor sa parehong class. Saan ito pinapayagang lumitaw?",
          "options": [
            {
              "icon": "",
              "label": "Kahit saan sa constructor body, basta tumakbo ito bago maibalik ang object"
            },
            {
              "icon": "",
              "label": "Bilang unang statement lang ng constructor — dapat unang linya ang this() (o ang super()), at hindi puwedeng tawagin ng isang constructor ang this() at super() nang magkasabay"
            },
            {
              "icon": "",
              "label": "Bilang huling statement lang, matapos makumpleto ang lahat ng field initialization"
            },
            {
              "icon": "",
              "label": "Sa mga constructor lang na explicit na minarkahan bilang delegating, gamit ang isang delegate keyword"
            }
          ]
        },
        {
          "question": "Kailangan mo ng list na madalas na iinsertan ng elemento sa harap, at bihira lang ang random-access reads. Alin ang mas mainam na structural fit, at bakit?",
          "options": [
            {
              "icon": "",
              "label": "ArrayList — pinapabilis ng contiguous backing array nito ang bawat operation, kasama ang front-insertion, kaysa sa linked structure"
            },
            {
              "icon": "",
              "label": "Magkapareho ang performance nila, dahil pareho silang nag-i-implement ng List interface na may parehong time guarantees"
            },
            {
              "icon": "",
              "label": "LinkedList — O(1) ang pag-insert sa harap dahil nire-relink lang nito ang isang node, habang ang ArrayList ay kailangang i-shift ang bawat existing na elemento nang isa, kaya O(n) ang front-insertion"
            },
            {
              "icon": "",
              "label": "LinkedList, dahil sinusuportahan nito ang random access sa O(1) habang hindi ito kaya ng ArrayList"
            }
          ]
        },
        {
          "question": "Nag-insert ka ng limang entries sa isang plain HashMap nang may tiyak na order, tapos ini-iterate mo ito gamit ang for-each loop. Anong order ang lalabasan ng mga entries?",
          "options": [
            {
              "icon": "",
              "label": "Ang parehong order kung paano na-insert ang mga entries, dahil laging pina-preserve ng Java maps ang insertion order"
            },
            {
              "icon": "",
              "label": "Walang guaranteed na order — nakadepende ang iteration order ng HashMap sa hash bucket placement, hindi sa insertion order, at maaari pa itong magbago sa pagitan ng mga run; ang LinkedHashMap ang nagpe-preserve ng insertion order"
            },
            {
              "icon": "",
              "label": "Awtomatikong naka-sort ayon sa key, tulad ng paggawi ng TreeMap"
            },
            {
              "icon": "",
              "label": "Reverse ng insertion order, dahil internally ay gumagamit ng stack ang HashMap"
            }
          ]
        },
        {
          "question": "Ilang null key ang kayang hawakan ng plain java.util.HashMap nang sabay, at ilang null value?",
          "options": [
            {
              "icon": "",
              "label": "Walang kailanman pinapayagang null key at null value sa anumang Map implementation"
            },
            {
              "icon": "",
              "label": "Isang null key lang ang pinakamarami, at kahit gaano karaming null values — pinapayagan ng HashMap ang iisang null key, hindi tulad ng Hashtable na hindi pumapayag sa alinman"
            },
            {
              "icon": "",
              "label": "Walang limitasyong null keys at null values, dahil itinuturing ang null tulad ng ibang key"
            },
            {
              "icon": "",
              "label": "Isang null key at isang null value ang maximum, pareho na naka-cap sa isa"
            }
          ]
        },
        {
          "question": "Ini-iterate mo ang List gamit ang for-each loop at tinatawag ang list.remove(item) direkta sa list mula sa loob ng loop body, sa ilan pero hindi lahat ng elemento. Ano ang mangyayari?",
          "options": [
            {
              "icon": "",
              "label": "Gumagana ito nang tama at inaalis ang eksaktong mga elementong nilalayon"
            },
            {
              "icon": "",
              "label": "Tahimik nitong nilalaktawan ang elemento pagkatapos ng inalis, pero kumpleto naman ito nang walang error"
            },
            {
              "icon": "",
              "label": "Nagta-throw ito ng IndexOutOfBoundsException kapag naabot ng loop ang lumang size ng list"
            },
            {
              "icon": "",
              "label": "Nagta-throw ito ng ConcurrentModificationException — nade-detect at tinatanggihan ang direktang pagbabago sa structure ng list habang may implicit na iterator na dumadaan dito; dapat gamitin ang Iterator.remove() sa halip"
            }
          ]
        },
        {
          "question": "Sa runtime, kung mayroon kang List<String> list, ano talaga ang mape-pag-alam mo tungkol sa generic type parameter nito sa pamamagitan ng reflection o instanceof?",
          "options": [
            {
              "icon": "",
              "label": "Puwede mong tawagin ang list.getElementType() para kunin ang String.class sa runtime"
            },
            {
              "icon": "",
              "label": "Nagko-compile ang instanceof List<String> at tama nitong sina-check ang element type"
            },
            {
              "icon": "",
              "label": "Iniimbak ng JVM ang type parameter bilang hidden metadata na naa-access sa pamamagitan ng list.getGenericType()"
            },
            {
              "icon": "",
              "label": "Wala — nabubura ang generic type information sa compile time, kaya sa runtime ay isa lang itong List, at walang paraan para malaman kung na-declare ito bilang List<String> o List<Integer>"
            }
          ]
        },
        {
          "question": "switch (day) { case 1: case 2: print(\"Weekday\"); break; case 6: print(\"Saturday\"); case 7: print(\"Sunday\"); break; default: print(\"?\"); } Kung 6 ang day, ano ang ipi-print?",
          "options": [
            {
              "icon": "",
              "label": "Saturday lang — laging humihinto ang bawat case block sa switch pagkatapos ng sarili nitong print statement"
            },
            {
              "icon": "",
              "label": "Sunday lang — nagsisimula ang matching sa case 6 pero ang huling matching label lang bago ang break ang eksekyut"
            },
            {
              "icon": "",
              "label": "Walang ipi-print, dahil walang matching case ang day 6 na may sariling break nang direkta sa ilalim nito"
            },
            {
              "icon": "",
              "label": "Saturday tapos Sunday — walang break ang case 6, kaya nag-fa-fall through ang execution papunta sa code ng susunod na case bago maabot ang sumusunod na break"
            }
          ]
        },
        {
          "question": "Kailangan ng isang Product class ng iisang, malinaw na \"natural\" sort order base sa price, kasama ang kakayahang mag-sort din ayon sa name o stock level sa iba't ibang bahagi ng codebase. Aling kombinasyon ang tamang design?",
          "options": [
            {
              "icon": "",
              "label": "I-implement ang Comparable<Product> nang tatlong hiwalay na beses, isa kada ordering, at hayaan ang caller na pumili kung aling compareTo ang tatakbo"
            },
            {
              "icon": "",
              "label": "I-implement ang Comparable<Product> para sa natural price ordering, at gumawa ng hiwalay na Comparator<Product> instances para sa name at stock-level orderings na ginagamit sa ibang lugar"
            },
            {
              "icon": "",
              "label": "Gumamit lang ng Comparator para sa bawat ordering, kasama ang price, dahil walang advantage ang Comparable dito"
            },
            {
              "icon": "",
              "label": "Gumamit lang ng Comparable sa pamamagitan ng pagdagdag ng tatlong overloaded compareTo methods, isa kada ordering"
            }
          ]
        },
        {
          "question": "May method na tumatawag ng new FileReader(path), na nagde-declare ng throws IOException. Ang IOException ay extends Exception, hindi RuntimeException. Ano ang dapat mong gawin para makakompile ito?",
          "options": [
            {
              "icon": "",
              "label": "Wala — ipinipilit lang ito ng compiler para sa mga exception na extends RuntimeException"
            },
            {
              "icon": "",
              "label": "Mag-catch ng IOException sa isang try/catch o mag-declare ng throws IOException sa sarili mong method — dapat asikasuhin o i-propagate nang explicit ang checked exceptions, hindi tulad ng unchecked RuntimeException subclasses"
            },
            {
              "icon": "",
              "label": "Balutin ang tawag sa isang try/catch para sa RuntimeException, dahil awtomatikong unchecked ang IOException sa modernong Java"
            },
            {
              "icon": "",
              "label": "I-declare ang method bilang static — exempted ang static methods sa checked exception handling"
            }
          ]
        },
        {
          "question": "Gumagamit ang try (Resource a = new Resource(\"A\"); Resource b = new Resource(\"B\")) { ... } ng dalawang resource na nag-i-implement ng AutoCloseable. Kung normal na natapos ang try block, anong order sila isasara?",
          "options": [
            {
              "icon": "",
              "label": "Una isasara ang A, tapos ang B, tumutugma sa declaration order"
            },
            {
              "icon": "",
              "label": "Una isasara ang B, tapos ang A — isinasara ng try-with-resources ang mga resource sa reverse ng order kung paano sila na-declare"
            },
            {
              "icon": "",
              "label": "Parehong isasara nang sabay, dahil pina-parallelize ng try-with-resources ang cleanup"
            },
            {
              "icon": "",
              "label": "B lang ang awtomatikong isasara — dapat pa ring isara nang manual ang A sa isang finally block"
            }
          ]
        },
        {
          "question": "int getValue() { try { return 1; } finally { return 2; } } Ano ang ibabalik ng pagtawag sa getValue()?",
          "options": [
            {
              "icon": "",
              "label": "1 — nakumpirma na ang return value ng try block bago tumakbo ang finally, kaya hindi ito mababago ng finally"
            },
            {
              "icon": "",
              "label": "Nagta-throw ito ng exception sa runtime, dahil hindi puwedeng mag-return ang method mula sa dalawang lugar"
            },
            {
              "icon": "",
              "label": "2 — ino-override at pinapalitan ng return statement sa loob ng finally ang anumang return na nasa proseso na mula sa try block, dini-discard nang buo ang value na 1"
            },
            {
              "icon": "",
              "label": "Compile error ito — hindi pinapayagang maglaman ng return statement ang finally"
            }
          ]
        },
        {
          "question": "try { ... } catch (IOException e) { ... } catch (FileNotFoundException e) { ... }, at ang FileNotFoundException ay extends IOException. Ano ang mangyayari kapag sinubukan mong i-compile ito?",
          "options": [
            {
              "icon": "",
              "label": "Compile error — unreachable ang FileNotFoundException catch block dahil ang mas naunang, mas general na IOException catch block ay tumutugma na sa bawat FileNotFoundException"
            },
            {
              "icon": "",
              "label": "Nagko-compile ito nang maayos, at tatakbo ang mas specific na FileNotFoundException block sa tuwing itinatapon ang eksaktong type na iyon"
            },
            {
              "icon": "",
              "label": "Nagko-compile ito nang maayos, at parehong catch block ang tatakbo nang sunud-sunod para sa isang FileNotFoundException"
            },
            {
              "icon": "",
              "label": "Ayos ito sa compile time pero nagta-throw ng runtime error sa unang beses na aktwal na mangyari ang FileNotFoundException"
            }
          ]
        },
        {
          "question": "May class na may synchronized instance method na process() at synchronized static method na configure(). Ano, partikular, ang lini-lock ng bawat isa?",
          "options": [
            {
              "icon": "",
              "label": "Nililock ng process() ang monitor ng specific na object instance na kinatawagan dito, habang nililock ng configure() ang monitor ng Class object mismo — shared ng bawat instance"
            },
            {
              "icon": "",
              "label": "Pareho nilang nililock ang iisang global lock para sa buong JVM, anuman ang instance o class"
            },
            {
              "icon": "",
              "label": "Nililock ng process() ang Class object, at nililock ng configure() ang anumang instance na nagkataong tumawag dito"
            },
            {
              "icon": "",
              "label": "Wala talaga silang nililock maliban kung may synchronized block din na ginamit sa loob ng method body"
            }
          ]
        },
        {
          "question": "May field na na-declare bilang volatile int counter = 0;, at maraming thread ang tumatakbo ng counter++ dito nang sabay-sabay. Napipigilan ba ng volatile ang lost updates dito?",
          "options": [
            {
              "icon": "",
              "label": "Oo — ginagawang atomic ng volatile ang bawat operation sa field, kasama ang increments"
            },
            {
              "icon": "",
              "label": "Hindi — ginagarantiyahan lang ng volatile na makikita ng reads ang pinakahuling write sa magkakaibang thread (visibility); ang counter++ ay isang read-modify-write na may maraming steps, at walang ginagawa ang volatile para gawing atomic ang mga steps na iyon"
            },
            {
              "icon": "",
              "label": "Oo, pero para lang sa int at long fields partikular, dahil sa kung paano hinahandle ng JVM ang 64-bit values"
            },
            {
              "icon": "",
              "label": "Hindi, at nabibigo rin ang volatile na i-guarantee ang visibility para sa primitive types tulad ng int"
            }
          ]
        },
        {
          "question": "Ang interface A at interface B ay pareho na nagde-declare ng default method na describe(). May class na nag-i-implement ng A at B pareho at hindi ini-override ang describe() mismo. Ano ang mangyayari?",
          "options": [
            {
              "icon": "",
              "label": "Awtomatikong pinipili ng compiler ang version ng interface A, dahil nakalista ito nang una sa implements clause"
            },
            {
              "icon": "",
              "label": "Parehong version ang tatakbo, isa pagkatapos ng isa, sa tuwing tinatawag ang describe()"
            },
            {
              "icon": "",
              "label": "Ayos ito sa compile time, pero nagta-throw ng AmbiguousMethodException sa unang beses na tawagin ang describe()"
            },
            {
              "icon": "",
              "label": "Compile error — kapag dalawang interface ang nag-contribute ng parehong default method, dapat i-override ito mismo ng implementing class para lutasin ang ambiguity, dahil hindi huhulaan ng Java kung alin ang ibig mong sabihin"
            }
          ]
        },
        {
          "question": "Isinusulat ang list.stream().filter(x -> x > 0).map(x -> x * 2); pero hindi na-assign ang resulta sa isang terminal operation tulad ng .collect() o .forEach(). Ano talaga ang mangyayari kapag na-execute ang linyang ito?",
          "options": [
            {
              "icon": "",
              "label": "Wala talagang nangyayari sa mga elemento ng list — ang filter at map ay lazy intermediate operations na nagbu-build lang ng pipeline description; kung walang terminal operation, hindi talaga tatakbo ang pipeline na iyon"
            },
            {
              "icon": "",
              "label": "Agad na nafi-filter at nama-map ang bawat elemento, eksakto na parang may tinawag na terminal operation"
            },
            {
              "icon": "",
              "label": "Ang filter lang ang agad na tatakbo; naka-defer ang map hanggang lumitaw ang isang terminal operation"
            },
            {
              "icon": "",
              "label": "Nagta-throw ito ng IllegalStateException, dahil nangangailangan ang stream pipeline ng terminal operation para makakompile"
            }
          ]
        }
      ],
      "optionOrderVersion": "0154f9576054ad6f"
    }
  },
  "testNames": {
    "java-test": "Pagsusulit sa Java"
  }
}
