{
  "assessmentTests": {
    "java_test": {
      "name": "Java Test",
      "desc": "30 คำถามสถานการณ์เกี่ยวกับไวยากรณ์พื้นฐาน กลศาสตร์ OOP คอลเลกชัน Generics ข้อยกเว้น และ Concurrency — ตรวจสอบว่าทักษะ Java ของคุณตรงกับความหมายของ Java proficiency ในประกาศรับสมัครงานหรือไม่",
      "recommendation": "โปรไฟล์ทักษะ Java ของคุณ",
      "results": {
        "beginner": {
          "name": "Beginner",
          "desc": "คุณเขียนคลาสและเมธอดที่ใช้ได้ แต่คำถามที่คุณตอบผิดรวมตัวอยู่ในเรื่อง Identity และค่าเริ่มต้นมากกว่า Syntax — String == เทียบกับ .equals, ว่าทำไม new String(\"x\") ถึงไม่ยอมใช้ string pool, ตัวเลขฟิลด์ค่าเริ่มต้นเป็นอะไร เทียบกับ wrapper field ทั้งหมดนี้ไม่ใช่เรื่องความไม่สามารถ Java เท่าไรแต่คือกฎเฉพาะที่ยอมลำบากคนที่เรียน Java จากการลองผิดลองถูกแทนที่จะเรียนจากวิธี References และ Primitives ทำงานจริง ๆ พวกนี้สำคัญในงานเพราะแต่ละอันคือจุดที่โค้ด Compile ได้, Run ได้, แต่เงียบ ๆ ทำอย่างอื่นแทน",
          "recommendation": "เริ่มต้นด้วยสามสิ่ง ตามลำดับนี้: ว่าทำไม == บน String object สองตัวจึงเปรียบเทียบ References ไม่ใช่ Characters (และ .equals คือสิ่งที่คุณต้องการเกือบตลอด) Int overflow ห่อเบา ๆ แทนที่จะ Throw, ว่าทำไม Integer field ที่ไม่ได้เริ่มต้นถึงค่าเริ่มต้นเป็น null ในขณะที่ int field ค่าเริ่มต้นเป็น 0 Official Java Tutorials และ Baeldung ต่างก็ครอบคลุมทั้งสามอย่างพร้อมตัวอย่างที่ Run ได้"
        },
        "intermediate": {
          "name": "Intermediate",
          "desc": "คุณจัดการโค้ด Application ประจำวัน ได้สบาย ๆ — คลาส คอลเลกชัน Control Flow ที่ตรงไปตรงมา — และคุณจะไม่ลดความเร็วลงจากงาน Feature ปกติ ช่องว่างระหว่างนี่กับ Advanced ส่วนใหญ่คือสิ่งที่เกิดขึ้นเมื่อ Java Rules โต้ตอบกับ Concurrency และ Generics: Static method ที่หลบหลีกโดย Declared Type แทน Object ที่คาดคิด HashMap Iteration Order ที่เงียบ ๆ คุณพึ่ง, ConcurrentModificationException จากการลบ Item ตรงกลาง Loop ปัญหาประเภทนี้ผ่าน Quick Read-through ได้ และเกิดขึ้นจริงเมื่อมี Specific Runtime Condition",
          "recommendation": "โฟกัสว่า Compiler's Static View ของโค้ดของคุณต่างจากสิ่งที่ Run จริง ๆ อย่างไร: Overload Resolution และ Static-Method Hiding โดย Declared Type ไม่ใช่ Runtime Type, ว่าทำไม HashMap ไม่ให้ Iteration-Order Guarantee, ว่าทำไมการแก้ List โดยตรงขณะ Iterate จึง Throw ConcurrentModificationException แล้ว Generics Erasure, เพราะปัญหานั้นมักจะลำบากคนที่รู้คอลเลกชันแต่ละตัวแล้วแล้ว"
        },
        "advanced": {
          "name": "Advanced",
          "desc": "นี่คือระดับที่ประกาศรับสมัครงานส่วนใหญ่หมายถึง \"strong Java\" คุณอ่านคลาสมี Static Blocks, Instance Blocks และ Constructors หลายตัว และทำนายลำดับที่ Run ได้แน่นอน คุณรู้ว่าทำไม Finally Block จึงพูดเพ้องปล่อยให้ Try Block's Return Value หายไป และคุณใช้ Try-With-Resources แทน Manual Finally-Close เพราะคุณรู้ Ordering Guarantee ที่มัน ให้ สิ่งแยกระดับนี้จาก Top คือ Concurrent และ Interface-Level ของงาน: สิ่งที่ Synchronized ล็อคจริง ๆ, สิ่งที่ Volatile ให้และไม่ให้, วิธีแก้ไข Default-Method Conflicts"
        },
        "expert": {
          "name": "Expert",
          "desc": "คุณให้คะแนนสูงสุดในทุกส่วน — Core Syntax และ Types, OOP Mechanics และ Scope, Collections และ Generics, Exceptions, Concurrency และ Idioms ในทางปฏิบัติหมายถึง คุณสามารถรับโค้ดของคนแปลกหน้ามาและอธิบายว่าทำไม Compile Error, Runtime Exception, หรือค่าที่เงียบ ๆ ผิดจึงเกิดขึ้น ไม่ใช่แค่ว่า Syntax บอกว่าควรเป็นอย่างไร ซึ่งเป็นทักษะที่ยากกว่าและมีค่ามากกว่า ที่ระดับนี้ภาษาตัวเองนั้นหนักไม่ค่อย; ขีด จำกัด มักจะเป็น Concurrency Design หรือรูปร่างของข้อมูลข้างล่าง",
          "recommendation": "ผลตอบแทน (Return) ตอนนี้ใน Design และ Diagnosis: อ่าน Thread Dump ก่อนสมมติว่าเป็น Deadlock, เลือกระหว่าง Synchronized, java.util.concurrent Locks และ Atomics เป็น Tradeoff ไม่ใช่ Default, Stream-Pipeline Design ที่ยาน Lazy ตั้งใจแทนเกิดบังเอิญ ถ้าคุณกำลังถูกคัดกรองสำหรับบทบาท บรรยายเกี่ยว Concurrency Bug เช่น Missed Happens-Before Edge หรือ ConcurrentModificationException ที่คุณพบในการ Produce แทนการตั้งชื่อ Java Features — มันแสดง Reasoning ไม่ใช่แค่ Vocabulary"
        }
      },
      "questions": [
        {
          "question": "คุณสร้าง String object สองตัว: String a = new String(\"cat\"); String b = new String(\"cat\"); a == b ประเมินค่าเป็นอะไร?",
          "options": [
            {
              "icon": "",
              "label": "true — String Literals ที่มี Characters เดียวกันจะเป็น Object เดียวกันเสมอ"
            },
            {
              "icon": "",
              "label": "true — new String(...) ยอมใช้ String Pool ใหม่ ดังนั้นข้อความที่เหมือนกันจึงแชร์ Object หนึ่งตัว"
            },
            {
              "icon": "",
              "label": "Compile Error — == ไม่สามารถใช้เปรียบเทียบ String Objects ได้"
            },
            {
              "icon": "",
              "label": "false — new String(...) ตั้งเตอร์ Allocate Object ใหม่บน Heap เสมอ ดังนั้น == เปรียบเทียบ References ต่างกันสองตัว แม้ว่า .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 — Autoboxed Integer Objects ถูก Cache ตลอดไม่ว่าค่าเท่าไหร่"
            },
            {
              "icon": "",
              "label": "false แล้ว false — == บน Integer Objects จะเป็น Reference Comparison เสมอ ดังนั้นค่าที่เท่ากันจึงไม่เคยตรงกัน"
            },
            {
              "icon": "",
              "label": "true แล้ว false แต่เพียง 200 Overflow ของ Byte เท่านั้น — Cache Boundary ไม่เกี่ยวกับ -128..127"
            },
            {
              "icon": "",
              "label": "true แล้ว false — Autoboxed Integer Values จาก -128 ถึง 127 ถูก Cache และแชร์ ดังนั้น 100 ใช้ Object หนึ่งตัว แต่ 200 ตกนอก Cache และ Autobox ไปยัง Objects สองตัวแยก"
            }
          ]
        },
        {
          "question": "int max = Integer.MAX_VALUE; System.out.println(max + 1); เกิดอะไรขึ้น?",
          "options": [
            {
              "icon": "",
              "label": "มัน Throw ArithmeticException สำหรับ Integer Overflow"
            },
            {
              "icon": "",
              "label": "มันพิมพ์ Integer.MAX_VALUE อีกครั้ง เพราะ Java Clamps ที่ Maximum ของ Type"
            },
            {
              "icon": "",
              "label": "มันพิมพ์ Integer.MIN_VALUE — Int Arithmetic Wrap Around เงียบ ๆ บน Overflow แทนที่จะ Throw"
            },
            {
              "icon": "",
              "label": "มัน Compile Error — Compiler Detects Overflow ล่วงหน้า"
            }
          ]
        },
        {
          "question": "System.out.println(0.1 + 0.2 == 0.3); นี่พิมพ์อะไร และทำไม?",
          "options": [
            {
              "icon": "",
              "label": "false — 0.1, 0.2 และ 0.3 ไม่สามารถแทนได้อย่างแน่นอนใน Binary Floating Point ดังนั้นผลบวกจึงมี Rounding Error ที่ทำให้มันไม่เท่า Bit-For-Bit กับ 0.3"
            },
            {
              "icon": "",
              "label": "true — Java Round Double Arithmetic ไปยัง Nearest Representable Decimal ก่อนเปรียบเทียบ"
            },
            {
              "icon": "",
              "label": "true — Addition ของ Doubles สองตัวเสมอถูกต้องสำหรับค่าที่มี Decimal Digits สองตัว"
            },
            {
              "icon": "",
              "label": "Throw Exception เพราะ == ไม่นิยาม Double ใน Java"
            }
          ]
        },
        {
          "question": "คลาสประกาศ Instance Fields สองตัวไม่มี Initializer: int count; และ Integer total; ก่อน Constructor ทำงาน ค่าเริ่มต้นคือเท่าไหร่?",
          "options": [
            {
              "icon": "",
              "label": "ทั้งสองค่าเริ่มต้นเป็น 0 เพราะ Integer Autoboxes ไป int ที่ Field Initialization"
            },
            {
              "icon": "",
              "label": "count เป็น 0 และ total เป็น 0 ถูก Boxed โดยอัตโนมัติในครั้งแรกที่มันถูกอ่าน"
            },
            {
              "icon": "",
              "label": "count เป็น 0 และ total เป็น null — Primitive Numeric Fields ค่าเริ่มต้นเป็นศูนย์ แต่ Uninitialized Wrapper Reference Field ค่าเริ่มต้นเป็น null เหมือน Object Reference อื่นใด"
            },
            {
              "icon": "",
              "label": "ทั้งสองค่าเริ่มต้นเป็น null จนกว่าจะมี Assign อย่างชัดแจ้ง เพราะ Java ไม่มี Implicit Numeric Defaults"
            }
          ]
        },
        {
          "question": "Loop ทำงาน 1000 ครั้ง แต่ละครั้งทำ result += \"x\"; บน String result. เกิดอะไรขึ้นจริง ๆ ภายใน แต่ละ Iteration?",
          "options": [
            {
              "icon": "",
              "label": "Character Array ของ String Object ที่มีอยู่ขยายในตำแหน่งเดิม"
            },
            {
              "icon": "",
              "label": "Java โดยอัตโนมัติ Batch Concatenations และ Allocate เพียง Object String สุดท้ายเดียว"
            },
            {
              "icon": "",
              "label": "Compile ไป Single StringBuilder.append() ที่แชร์ข้ามทั้ง 1000 Iterations ไม่มี Object เพิ่มเติม Allocate ต่อ Iteration"
            },
            {
              "icon": "",
              "label": "Object String ใหม่สร้างขึ้นและ result Reassign ไปชี้ที่มัน — String Object ก่อนหน้าถูกทิ้งไป เพราะ String Immutable และ += ไม่สามารถแก้ไขมันในตำแหน่งเดิม"
            }
          ]
        },
        {
          "question": "final List<String> names = new ArrayList<>(); ข้อใดต่อไปนี้เป็นจริง?",
          "options": [
            {
              "icon": "",
              "label": "names.add(\"Ana\") Compile และทำงานได้ดี — final เพียง Prevent Reassign names Reference ตัวเองเท่านั้น ไม่ใช่ Mutate Object มันชี้ไป"
            },
            {
              "icon": "",
              "label": "names.add(\"Ana\") Compile Error เพราะ final ทำให้ List Unmodifiable"
            },
            {
              "icon": "",
              "label": "List Thread-Safe สำหรับ Concurrent Writes เพราะมันประกาศ final"
            },
            {
              "icon": "",
              "label": "final บน Local Variable ไม่มีผล เว้นแต่ Type ก็ประกาศ 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 — == เปรียบเทียบ Array References (Array Objects สองตัวต่างกัน) ในขณะที่ Arrays.equals เปรียบเทียบ Elements"
            },
            {
              "icon": "",
              "label": "true แล้ว true — Arrays ที่มี Contents เหมือนกันเป็น Object เดียวกันใน Java"
            },
            {
              "icon": "",
              "label": "false แล้ว false — Arrays.equals ใช้ได้กับ Object Arrays เท่านั้น ไม่ใช่ Primitive Int Arrays"
            },
            {
              "icon": "",
              "label": "true แล้ว false — == บน Arrays เปรียบเทียบ Contents และ 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 Inspect Actual Runtime Class ของ Object ก่อน Pick Overload"
            },
            {
              "icon": "",
              "label": "show(Object) ทำงาน — Overload Resolution Decide ที่ Compile Time โดยใช้ Declared Type ของ Variable ไม่ใช่ Actual Runtime Type ของ Object"
            },
            {
              "icon": "",
              "label": "Compile Error — Object ไม่สามารถผ่านไปยังจุดที่ Overload เฉพาะเจาะจงมากขึ้น"
            },
            {
              "icon": "",
              "label": "Overload ทั้งสองทำงาน ครั้งละหนึ่งครั้ง เพราะ Java Resolve Overloads โดย Try ทุก Match"
            }
          ]
        },
        {
          "question": "Class Base มี static void greet() { print(\"Base\"); }. Class Derived extends Base และประกาศ static void greet() { print(\"Derived\"); }. คุณเขียน: Base ref = new Derived(); ref.greet(); พิมพ์อะไร?",
          "options": [
            {
              "icon": "",
              "label": "Derived — Static Methods Override เหมือน Instance Methods ตาม Actual Object's Runtime Type"
            },
            {
              "icon": "",
              "label": "Compile Error — Static Methods ไม่สามารถเรียกผ่าน Instance Reference"
            },
            {
              "icon": "",
              "label": "Base — Static Methods ไม่ Polymorphic; Calling หนึ่งผ่าน Reference Resolve โดย Reference's Declared Type ที่ Compile Time ไม่ใช่ Object's Actual Type"
            },
            {
              "icon": "",
              "label": "Base และ Derived พิมพ์ทั้งคู่ เพราะ Call Resolve ไป Hidden และ Hiding Versions ทั้งสอง"
            }
          ]
        },
        {
          "question": "ภายใน Method คุณเขียน int count = 0; แล้วพยายาม Reference count จาก Lambda ผ่านไปยัง Method อื่น มีอะไรที่ต้องเป็นจริงเกี่ยว count สำหรับ Compile นี้?",
          "options": [
            {
              "icon": "",
              "label": "count ต้อง Effectively Final — ไม่มี Reassign ที่ใดก็ตามหลังจาก Value เริ่มต้น — เพราะ Lambda Capture Snapshot ไม่ใช่ Live Reference ไปยัง Mutable Local Variable"
            },
            {
              "icon": "",
              "label": "ไม่มีอะไร — Local Variable ใดก็ตามสามารถอ่านและ Reassign อย่างเสรีจาก Lambda"
            },
            {
              "icon": "",
              "label": "count ต้องประกาศ volatile เพื่อให้ Lambda เห็น Latest Value"
            },
            {
              "icon": "",
              "label": "count ต้องเป็น Field ไม่ใช่ Local Variable — Lambdas ไม่สามารถ Capture Locals เลย"
            }
          ]
        },
        {
          "question": "void rename(StringBuilder sb) { sb = new StringBuilder(\"new\"); } เรียกว่า StringBuilder original = new StringBuilder(\"old\"); rename(original); original หลัง Call คืออะไร?",
          "options": [
            {
              "icon": "",
              "label": "Become \"new\" — Objects ผ่าน Reference ใน Java ดังนั้น Reassign Parameter ทำให้เปลี่ยน Caller's Variable ด้วย"
            },
            {
              "icon": "",
              "label": "Become \"new\" เพียง Mutable Types เช่น StringBuilder แต่ไม่ใช่ Immutable Types"
            },
            {
              "icon": "",
              "label": "Still \"old\" — Java ผ่าน Reference ตัวเองโดย Value ดังนั้น Reassign Parameter ภายใน Method เพียง Repoint Local Copy ของ Reference ทิ้ง Caller's Original ไม่เปลี่ยน"
            },
            {
              "icon": "",
              "label": "Throw Runtime Exception เพราะ sb ถูก Reassign ภายใน Method"
            }
          ]
        },
        {
          "question": "คลาสมี Static Initializer Block, Instance Initializer Block, และ Constructor ตามลำดับ Source นั้น คุณสร้าง Objects สองตัวของ Class นี้ทีละ ๆ ลำดับไหนสิ่งเหล่านี้ทำงาน?",
          "options": [
            {
              "icon": "",
              "label": "Static Block ทำงานเพียงครั้งเดียว ครั้งแรก Class โหลด; แล้ว Object แต่ละตัว Instance Block ทำงาน แล้ว Constructor Body ทำงาน"
            },
            {
              "icon": "",
              "label": "ทั้งสามทำงาน Fresh ตามลำดับ Source Object เดี่ยว ๆ"
            },
            {
              "icon": "",
              "label": "Constructor ทำงาน Object แต่ละตัว แล้ว Instance Block แล้ว Static Block ครั้งเดียวที่ท้ายสุด"
            },
            {
              "icon": "",
              "label": "Static Block ทำงาน Object ครั้งละ Right ก่อน Instance Block"
            }
          ]
        },
        {
          "question": "คลาสมี void log(String s) และ void log(String... args). คุณเรียก log(\"hi\"). Overload ไหนทำงาน?",
          "options": [
            {
              "icon": "",
              "label": "log(String... args) — Varargs Overloads ถูก Prefer ตลอดเมื่อทั้งสองใช้ได้"
            },
            {
              "icon": "",
              "label": "Compile Error — Call Ambiguous ระหว่าง Overloads ทั้งสอง"
            },
            {
              "icon": "",
              "label": "log(String s) — Fixed-Arity Overload ตรงกันแน่นอน Java ทำให้ Prefer ไป Varargs Overload ซึ่ง Last Resort เท่านั้น"
            },
            {
              "icon": "",
              "label": "อัน Declare ก่อนใน Source File ทำงาน"
            }
          ]
        },
        {
          "question": "Constructor's บรรทัดแรกเรียก this(0); เพื่อ Delegate ไปยัง Constructor อื่นใน Class เดียวกัน this() ที่ไหน Appear ได้?",
          "options": [
            {
              "icon": "",
              "label": "ที่ใดก็ตามใน Constructor Body ตราบเท่า Run ก่อน Object ส่งคืน"
            },
            {
              "icon": "",
              "label": "เพียง Very First Statement ของ Constructor — this() (หรือ super()) ต้อง First Line และ Constructor ไม่สามารถเรียก this() และ super() ทั้งคู่"
            },
            {
              "icon": "",
              "label": "เพียง Last Statement หลังจาก Field Initialization ทั้งหมด Complete"
            },
            {
              "icon": "",
              "label": "เพียง Constructors ที่ Mark Explicitly เป็น Delegating โดยใช้ Delegate Keyword"
            }
          ]
        },
        {
          "question": "คุณต้อง List ที่จะมี Elements Insert ที่ Front อย่างบ่อย ๆ และ Random-Access Reads ไม่บ่อย ที่โครงสร้าง ไหนเหมาะสม และทำไม?",
          "options": [
            {
              "icon": "",
              "label": "ArrayList — Contiguous Backing Array ทำให้ทุก Operation รวม Front-Insertion เร็วกว่า Linked Structure"
            },
            {
              "icon": "",
              "label": "Perform Identically เพราะทั้งสอง Implement List Interface พร้อม Time Guarantees เดียวกัน"
            },
            {
              "icon": "",
              "label": "LinkedList — Insert ที่ Front เป็น O(1) เพราะเพียง Relink Node ขณะ ArrayList ต้อง Shift ทุก Existing Element Up By One ทำให้ Front-Insertion O(n)"
            },
            {
              "icon": "",
              "label": "LinkedList เพราะ Support Random Access ใน O(1) ขณะ ArrayList ไม่"
            }
          ]
        },
        {
          "question": "คุณ Insert Entries ห้าตัวลงใน Plain HashMap ตามลำดับเฉพาะ แล้ว Iterate ผ่าน For-Each Loop Entries มาในลำดับไหน?",
          "options": [
            {
              "icon": "",
              "label": "Insertion Order เดียวกัน เพราะ Java Maps ทำให้ Preserve Insertion Order เสมอ"
            },
            {
              "icon": "",
              "label": "Guaranteed Order ไม่มี — HashMap Iteration Order ขึ้นอยู่ Hash Bucket Placement ไม่ Insertion Order และสามารถเปลี่ยนได้ระหว่าง Runs; LinkedHashMap คือสิ่งที่ Preserve Insertion Order"
            },
            {
              "icon": "",
              "label": "Sorted โดย Key โดยอัตโนมัติ Behavior เดียวกับ TreeMap"
            },
            {
              "icon": "",
              "label": "Reverse ของ Insertion Order เพราะ HashMap Internally ใช้ Stack"
            }
          ]
        },
        {
          "question": "Plain java.util.HashMap สามารถถือ Null Keys กี่ตัวต่อครั้งและ Null Values กี่ตัว?",
          "options": [
            {
              "icon": "",
              "label": "ไม่มี Null Keys และ Null Values ไม่เคยอนุญาตใน Map Implementation ใดก็ตาม"
            },
            {
              "icon": "",
              "label": "Max Null Keys หนึ่ง และ Null Values จำนวนใดก็ได้ — HashMap ยอม Null Key หนึ่ง ไม่เหมือน Hashtable ซึ่งยินยอมไม่ "
            },
            {
              "icon": "",
              "label": "Unlimited Null Keys และ Unlimited Null Values เพราะ Null ถูก Treat เหมือน Key อื่นใด"
            },
            {
              "icon": "",
              "label": "Max Null Key หนึ่ง และ Max Null Value หนึ่ง ทั้งสอง Capped ที่หนึ่ง"
            }
          ]
        },
        {
          "question": "คุณ Iterate List ด้วย For-Each Loop และเรียก list.remove(item) โดยตรงบน List จาก Body Loop บาง Elements แต่ไม่ใช่ทั้งหมด เกิดอะไร?",
          "options": [
            {
              "icon": "",
              "label": "ทำงานได้ถูกต้องและลบ Elements ตั้งใจเท่านั้น"
            },
            {
              "icon": "",
              "label": "เงียบ ๆ Skip Element หลังตัวที่ลบ แต่ Complete ไม่มี Error"
            },
            {
              "icon": "",
              "label": "Throw IndexOutOfBoundsException เมื่อ Loop ถึง Old Size ของ List"
            },
            {
              "icon": "",
              "label": "Throw ConcurrentModificationException — Modify List Structure โดยตรงขณะ Implicit Iterator Walk มัน Detect และ Reject; Iterator.remove() ต้องใช้แทน"
            }
          ]
        },
        {
          "question": "ที่ Runtime ให้ List<String> list คุณสามารถหาว่า Generic Type Parameter อะไรได้ Reflection หรือ instanceof?",
          "options": [
            {
              "icon": "",
              "label": "คุณสามารถเรียก list.getElementType() ดึง String.class ที่ Runtime"
            },
            {
              "icon": "",
              "label": "instanceof List<String> Compile และ Correctly Check Element Type"
            },
            {
              "icon": "",
              "label": "JVM Stores Type Parameter เป็น Hidden Metadata Accessible ผ่าน list.getGenericType()"
            },
            {
              "icon": "",
              "label": "ไม่มีอะไร — Generic Type Information Erase ที่ Compile Time ดังนั้น Runtime Object เป็นเพียง List และไม่มีวิธี Recover ว่า Declare 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 Block แต่ละอัน Switch ทำงานหยุด Print Statement ตัวเองเสมอ"
            },
            {
              "icon": "",
              "label": "เพียง Sunday — Matching ควร Case 6 แต่เพียง Last Matching Label ก่อน Break ทำงาน"
            },
            {
              "icon": "",
              "label": "ไม่มีอะไรพิมพ์ เพราะ day 6 ไม่มี Matching Case ที่ Break ตัวเองมี Direct ภายใต้"
            },
            {
              "icon": "",
              "label": "Saturday แล้ว Sunday — case 6 ไม่มี Break ดังนั้น Execute Fall Through ไปยัง Next Case Code ก่อน Hit Following Break"
            }
          ]
        },
        {
          "question": "คลาส Product ต้อง Single Obvious \"Natural\" Sort Order โดย Price บวก Ability ที่จะ Sort โดย Name หรือ Stock Level ต่าง ๆ ตำแหน่ง Codebase ไหน ไหนเป็นจุดประสงค์ Design ที่ถูกต้อง?",
          "options": [
            {
              "icon": "",
              "label": "Implement Comparable<Product> สามครั้งแยก ครั้งละ Ordering และปล่อยให้ Caller เลือก compareTo ไหนทำงาน"
            },
            {
              "icon": "",
              "label": "Implement Comparable<Product> สำหรับ Natural Price Ordering และเขียน Separate Comparator<Product> Instances สำหรับ Name และ Stock-Level Orderings ใช้ที่อื่น"
            },
            {
              "icon": "",
              "label": "ใช้เพียง Comparator ทุก Ordering รวม Price เพราะ Comparable ไม่มี Advantage ที่นี่"
            },
            {
              "icon": "",
              "label": "ใช้เพียง Comparable โดย Add Three Overloaded compareTo Methods ครั้งละ Ordering"
            }
          ]
        },
        {
          "question": "Method เรียก new FileReader(path) ซึ่ง Declare throws IOException. IOException extends Exception ไม่ใช่ RuntimeException. อะไรต้องทำเพื่อ Compile นี้?",
          "options": [
            {
              "icon": "",
              "label": "ไม่มีอะไร — Compiler บังคับเฉพาะ Exceptions ที่ extend RuntimeException"
            },
            {
              "icon": "",
              "label": "Either Catch IOException ใน Try/Catch หรือ Declare throws IOException บน Method ตัวของคุณ — Checked Exceptions ต้อง Handle หรือ Propagate อย่างชัดแจ้ง ไม่เหมือน Unchecked RuntimeException Subclasses"
            },
            {
              "icon": "",
              "label": "Wrap Call ใน Try/Catch สำหรับ RuntimeException เพราะ IOException Automatically Unchecked ใน Modern Java"
            },
            {
              "icon": "",
              "label": "Declare Method เป็น Static — Static Methods ยกเว้นจาก Checked Exception Handling"
            }
          ]
        },
        {
          "question": "try (Resource a = new Resource(\"A\"); Resource b = new Resource(\"B\")) { ... } ใช้ Resources สองตัว Implement AutoCloseable. ถ้า Try Block Finish Normally ลำดับไหน Close?",
          "options": [
            {
              "icon": "",
              "label": "A Close First แล้ว B Matching Declaration Order"
            },
            {
              "icon": "",
              "label": "B Close First แล้ว A — Try-With-Resources Close Resources ใน Reverse ของ Order Declare"
            },
            {
              "icon": "",
              "label": "ทั้งสอง Close Simultaneously เพราะ Try-With-Resources Parallelize Cleanup"
            },
            {
              "icon": "",
              "label": "เพียง B Auto Close — A ยังต้อง Close Manually ใน Finally Block"
            }
          ]
        },
        {
          "question": "int getValue() { try { return 1; } finally { return 2; } } Calling getValue() ส่งคืนอะไร?",
          "options": [
            {
              "icon": "",
              "label": "1 — Try Block's Return Value ได้ Commit แล้วก่อน Finally ทำงาน ดังนั้น Finally ไม่สามารถเปลี่ยน"
            },
            {
              "icon": "",
              "label": "Throw Exception ที่ Runtime เพราะ Method ไม่สามารถ Return จาก Two Places"
            },
            {
              "icon": "",
              "label": "2 — Return Statement ข้างใน Finally Override และ Replace ใดก็ตามที่ Return Already Progress จาก Try Block ทิ้ง Value 1 ทั้งหมด"
            },
            {
              "icon": "",
              "label": "Compile Error — Finally ไม่อนุญาต Contain Return Statement"
            }
          ]
        },
        {
          "question": "try { ... } catch (IOException e) { ... } catch (FileNotFoundException e) { ... } และ FileNotFoundException extends IOException. เกิดอะไรเมื่อคุณพยายาม Compile?",
          "options": [
            {
              "icon": "",
              "label": "Compile Error — FileNotFoundException Catch Block Unreachable เพราะ Earlier General IOException Catch Block Already Match Every FileNotFoundException"
            },
            {
              "icon": "",
              "label": "Compile ได้ดี และ Specific FileNotFoundException Block ทำงาน Whenever Exception Type Exact Throw"
            },
            {
              "icon": "",
              "label": "Compile ได้ดี และทั้งสอง Catch Blocks ทำงาน Order สำหรับ FileNotFoundException"
            },
            {
              "icon": "",
              "label": "Fine ที่ Compile Time แต่ Throw Runtime Error First Time FileNotFoundException Actually Occur"
            }
          ]
        },
        {
          "question": "คลาสมี Synchronized Instance Method process() และ Synchronized Static Method configure(). สิ่งไหน Specifically สิ่งนี้แต่ละตัวล็อค?",
          "options": [
            {
              "icon": "",
              "label": "process() ล็อค Monitor ของ Specific Object Instance มันเรียก On ขณะ configure() ล็อค Monitor ของ Class Object ตัวเอง — Shared โดย ทุก Instance"
            },
            {
              "icon": "",
              "label": "ทั้งสอง ล็อค Single Global Lock เดียว JVM ทั้งหมด โดยไม่คำนึงถึง Instance หรือ Class"
            },
            {
              "icon": "",
              "label": "process() ล็อค Class Object และ configure() ล็อค Whichever Instance Happen Call มัน"
            },
            {
              "icon": "",
              "label": "Neither Lock Anything เว้นแต่ Synchronized Block ยัง Use ข้างใน Method Body"
            }
          ]
        },
        {
          "question": "Field Declare volatile int counter = 0; และ Multiple Threads Run counter++ บน Concurrent. Volatile Prevent Lost Updates ที่นี่?",
          "options": [
            {
              "icon": "",
              "label": "ใช่ — Volatile ทำให้ทุก Operation บน Field Atomic รวม Increments"
            },
            {
              "icon": "",
              "label": "ไม่ — Volatile เพียง Guarantee Reads See Latest Write ข้ามสอง Threads (Visibility); counter++ คือ Read-Modify-Write พร้อม Multiple Steps และ Volatile ทำไม่ให้สิ่งเหล่านั้น Atomic"
            },
            {
              "icon": "",
              "label": "ใช่ แต่เพียง Int และ Long Fields Specifically เนื่องจาก วิธี JVM Handle 64-Bit Values"
            },
            {
              "icon": "",
              "label": "ไม่ และ Volatile Failed Guarantee Visibility สำหรับ Primitive Types เช่น Int"
            }
          ]
        },
        {
          "question": "Interface A และ Interface B ต่างก็ Declare Default Method describe(). Class Implement ทั้งสอง A และ B และ ไม่ Override describe() เอง. เกิดอะไร?",
          "options": [
            {
              "icon": "",
              "label": "Compiler Pick Interface A's Version โดยอัตโนมัติ เพราะ List ก่อน Implements Clause"
            },
            {
              "icon": "",
              "label": "ทั้งสอง Versions ทำงาน ทีละอันเมื่อใดก็ตาม describe() Call"
            },
            {
              "icon": "",
              "label": "Fine ที่ Compile Time แต่ Throw AmbiguousMethodException First Time describe() Call"
            },
            {
              "icon": "",
              "label": "Compile Error — Two Interfaces Contribute Default Method เดียวกัน Implementing Class ต้อง Override มันตัวเอง Resolve Ambiguity เพราะ Java จะไม่เดาที่คุณหมายถึง"
            }
          ]
        },
        {
          "question": "list.stream().filter(x -> x > 0).map(x -> x * 2); เขียน แต่ Result ไม่เคย Assign Terminal Operation เช่น .collect() หรือ .forEach(). เกิดอะไรจริง ๆ เมื่อ Line นี้ Execute?",
          "options": [
            {
              "icon": "",
              "label": "ไม่มีอะไรเกิดขึ้นกับ List's Elements เลย — Filter และ Map Lazy Intermediate Operations ที่เพียง Build Up Pipeline Description; ไม่มี Terminal Operation Pipeline ไม่ Run"
            },
            {
              "icon": "",
              "label": "ทุก Element Filter และ Map โดยทันที Exactly เสมือนว่า Terminal Operation Call"
            },
            {
              "icon": "",
              "label": "เพียง Filter Run โดยทันที; Map Defer จนกว่า Terminal Operation ปรากฏ"
            },
            {
              "icon": "",
              "label": "Throw IllegalStateException เพราะ Stream Pipeline ต้อง Terminal Operation Compile"
            }
          ]
        }
      ],
      "optionOrderVersion": "0154f9576054ad6f"
    }
  }
}
