ข้าม​ไป​ยัง​เนื้อหา

รับ​อะไร​เข้า​ทีม​ก่อน · เรียง​ตาม​สิ่ง​ที่​วัด​ได้

เจ็ด​บท​ที่​ผ่าน​มา​วัด​ของ​ใหม่​ที​ละ​อย่าง · บท​นี้​เอา​ผล​มา​เรียง​เป็น​ลำดับ

และ​เกณฑ์​ที่​ใช้​เรียง​มี​สอง​ข้อ​เท่านั้น

ข้อ​แรก​วัด​สิ่ง​ที่​ได้ ข้อ​ที่​สอง​วัด​ความ​เสี่ยง​ตอน​ย้าย

ข้อ​แรก · ของ​นั้น​บังคับ​ความ​ถูก​ต้อง​ให้​ตอน​แปล​หรือ​ไม่

ของ​ที่​ทำให้ compiler จับ​ความ​ผิด​พลาด​แทน​คน​ได้ คุ้ม​ที่สุด เพราะ​มัน​ได้​ผล​ตลอด​ไป โดย​ไม่​ต้อง​มี​ใคร​คอย​ระวัง

ข้อ​ที่​สอง · มัน​ทำให้​ของ​ที่​เคย​ทำงาน​อยู่​พัง​ได้​หรือ​ไม่

ของ​ที่​เปลี่ยน​ความ​หมาย​ของ code เดิม​เงียบๆ ต้อง​รับ​ด้วย​ความ​ระวัง ไม่ใช่​ด้วย​การก​วาด​ทั้ง​โปร​เจ​กต์

เรียง​จาก​คุ้ม​ที่สุด​และ​ปลอดภัย​ที่สุด ลง​ไป​หา​ของ​ที่​ต้อง​คิด​ก่อน

ลำดับของบังคับ​ตอน​แปลทำ​ของ​เดิม​พัง​ได้
1recordใช่ไม่
2sealed + expression switchใช่ไม่
3record patternใช่ได้ · เรื่อง null
4Gatherersไม่ไม่
5virtual threadไม่ไม่
6StructuredTaskScopeไม่ได้ · ยัง preview

สาม​อันดับ​แรก​ได้​ประโยชน์​จาก​ข้อ​แรก​ทั้งหมด · และ​มี​เพียง​อันดับ​ที่ 3 ที่​ติด​ข้อ​ที่​สอง

ไม่ใช่​การก​วาด​ทั้ง​โปร​เจ​กต์​ใน​สัปดาห์​เดียว

record · ใช้​กับ​ของ​ใหม่​ทั้งหมด แล้ว​ปล่อย​ของ​เก่า​ไว้ · ชนิด​ที่​มี​อยู่​แล้ว​และ​ทำงาน​ถูก​อยู่ ไม่​ได้​ผิด​อะไร · ประโยชน์​ของ record อยู่​ที่​ชนิด​ที่​ยัง​ไม่​ถูก​เขียน

sealed + expression switch · เริ่ม​จาก​ที่​ที่​มี switch เหนือ enum อยู่​แล้ว · บท​ที่ 3 แสดง​ว่า​รูป statement เหนือ enum คือ​ช่อง​เดียว​ที่ compiler ไม่​บังคับ · เปลี่ยน​ที่​เหล่า​นั้น​เป็น expression switch คือ​การ​ย้าย​จาก​ช่อง​ที่​ไม่มี​ใคร​ดู ไป​ช่อง​ที่​มี​คน​ดู โดย​ไม่​ต้อง​เปลี่ยน​โครงสร้าง​อะไร​เลย

record pattern · ใช้​กับ code ใหม่ ส่วน code เก่า​ให้​ตรวจ null ก่อน​ย้าย · นี่​คือ​อันดับ​เดียว​ใน​สาม​อันดับ​แรก​ที่​ทำ​ของ​เดิม​พัง​ได้

ข้อ​ที่​ต้อง​รู้​ก่อน​เปลี่ยน `enum` เป็น `sealed` ใน​ของ​ที่ deploy แยก​ส่วน

switch ที่​ครอบ sealed ครบ ถูก​แปล​โดยที่ compiler รับ​ประกัน​ว่า​ไม่มี​ทาง​ตก​กิ่ง

วัน​ที่​มี​คน​เพิ่ม​ชนิด​ลูก​เข้าไป​แล้ว deploy เฉพาะ​ฝั่ง​ที่​ประกาศ​ชนิด โดย​ไม่​ได้​แปล​ฝั่ง​ผู้​เรียก​ใหม่ · ฝั่ง​ผู้​เรียก​จะ​เจอ​ค่าที่​ไม่มี​กิ่ง​ไหน​รับ แล้ว​โยน MatchExceptionMatchExceptionexception ที่ JVM โยน​เมื่อ​ไม่มี​กิ่ง​ไหน​ตรง ใน​รูป​ที่ compiler เคย​รับ​ประกัน​ว่า​ครบ · มัน​โผล่​เมื่อ​ชนิด​ลูก​ถูก​เพิ่ม​หลัง​จาก​ที่​ผู้​เรียก​ถูก​แปล​ไป​แล้ว ออก​มา​ตอน​รัน

ข้อ​นี้​ไม่ใช่​ข้อ​เสีย​ของ sealed · มัน​คือ​สิ่ง​ที่ enum ก็​เจอ​ใน​รูป​ของ​มัน​เอง แค่​เงียบ​กว่า · แต่​ถ้า​ทีม​คุณ deploy ที​ละ​ส่วน ต้อง​รู้​ว่า​อะไร​จะ​โผล่​มา

flowchart TB
  Q1{"บังคับความถูกต้องตอนแปลไหม"}
  Q1 -->|"ใช่"| Q2{"ทำของเดิมพังได้ไหม"}
  Q1 -->|"ไม่"| L["รับเมื่อมีงานที่มันแก้ได้จริง"]
  Q2 -->|"ไม่"| A["รับได้เลย · record · sealed"]
  Q2 -->|"ได้"| B["รับกับของใหม่ก่อน · record pattern"]

คำ​บรรยาย​ภาพ: สอง​คำถาม กับ​สาม​คำ​ตอบ ที่​ใช้​กับ feature ตัว​ไหน​ก็ได้

ของ​ที่​ไม่​ได้​อยู่​ใน​ลำดับ เพราะ​มัน​ไม่ใช่​การ​ตัดสิน​ใจ

หัวข้อ​ที่​มีชื่อ​ว่า “ของ​ที่​ไม่​ได้​อยู่​ใน​ลำดับ เพราะ​มัน​ไม่ใช่​การ​ตัดสิน​ใจ”

บาง​อย่าง​รับ​มา​เลย​ได้​โดย​ไม่​ต้อง​คิด

  • text block ไม่​เปลี่ยน​ความ​หมาย​ของ​อะไร​เลย · ใช้​ตรง​ที่​มี string หลาย​บรรทัด
  • var เป็น​เรื่อง​รสนิยม ไม่ใช่​เรื่อง​ความ​ถูก​ต้อง
  • import moduleimport moduleการ​ประกาศ​นำ​เข้า​ทั้ง​โมดูล​ใน​บรรทัด​เดียว แทน​การ​ไล่​นำ​เข้าที​ละ​ชนิด · ทำให้​ตัวอย่าง​สั้น​ลง​มาก แต่​แลก​กับ​การ​ที่​ผู้​อ่าน​ไม่​เห็น​ว่า​ชนิด​แต่ละ​ตัว​มา​จาก​ไหน ทำให้​ตัวอย่าง​สั้น​ลง​มาก แต่​แลก​กับ​การ​ที่​ผู้​อ่าน​ไม่​เห็น​ว่า ชนิด​แต่ละ​ตัว​มา​จาก​ไหน · เหมาะ​กับ script และ​ตัวอย่าง​ใน​เอกสาร มากกว่า​กับ code ที่​คน​หลาย​คน​ต้อง​อ่าน

ปิด​ท้าย​ด้วย​ขอบเขต เพราะ​คอร์ส​ที่​ไม่​บอก​ขอบเขต อ่าน​เหมือน​คอร์ส​ที่​ตอบ​ได้​ทุก​อย่าง

  • ไม่มี build tool สัก​บท ทุก​ตัวอย่าง​แปล​ด้วย javac และ​รัน​ด้วย java
  • ไม่​แตะ framework เรื่อง​นั้น​เป็น​ของ คอร์ส Kotlin กับ Spring Boot
  • ไม่​วัด​ความเร็ว ทั้ง​แปดบท​ไม่มี​หน่วย​เวลา​สัก​ตัว · หน่วย​ที่​ใช้​คือ​สถานะ​การ​แปล · ข้อความ​ของ compiler · ชื่อ​และ​จำนวน member ใน bytecode · จำนวน thread · จำนวน​ครั้ง​ที่​ถูก​เรียก
  • ไม่​พูด​ถึง​ของ​ที่​ยัง​ไม่​เข้า​รุ่น​ไหน คอร์ส​นี้​พูด​ถึง​ของ​ที่​แปล​ได้​วัน​นี้​เท่านั้น

ของ​ที่​เอา​กลับ​ไป​ได้​จริง ไม่ใช่​รายการ feature แต่​เป็น​วิธี​ถาม

เมื่อ JDK รุ่น​ถัด​ไป​ออก และ​คุณ​เจอ​บทความ​ที่​บอก​ว่า​ของ​ใหม่​ดี​อย่างไร ให้​ถาม​สาม​ข้อ

  1. มัน​อยู่​สถานะ​ไหน​ใน​รุ่น​ที่​ผม​รัน · ตอบ​ด้วย​การ​แปล​สอง​รอบ​ตาม​บท​ที่ 1 ไม่ใช่​ด้วย​การ​เชื่อ​บทความ
  2. มัน​บังคับ​อะไร​ให้​ตอน​แปล · ถ้า​ไม่​บังคับ​อะไร​เลย มัน​คือ​ความ​สะดวก ไม่ใช่​ความ​ปลอดภัย
  3. มัน​ทำให้ code ที่​มี​อยู่​เปลี่ยน​ความ​หมาย​ไหม · ตอบ​ด้วย​การ​รัน​ของ​เก่า​กับ​ของ​ใหม่ ด้วย input เดียวกัน รวม​ถึง null

สาม​ข้อ​นี้​ไม่​ผูก​กับ​รุ่น​ไหน · และ​มัน​คือ​สิ่ง​ที่​คอร์ส​นี้​ทำ​ซ้ำ​แปด​รอบ

แปดบท กับ​ข้อ​สรุป​ที่​ต่าง​จาก​ที่​หลาย​คน​คาด​ไว้​ตอน​เริ่ม

คอร์ส​นี้​เริ่ม​ด้วย​คำถาม​ว่า ของ​พวก​นี้​ใช้ได้​จริง​แล้ว​หรือ​ยัง และ​ได้​อะไร​กลับ​มา

คำ​ตอบ​ที่​ได้​ไม่ใช่​รายการ feature · มัน​คือ​นิสัย​หนึ่ง​อย่าง คือ ถาม​เครื่อง​มือ​ที่​อยู่​บน​เครื่อง แทน​การ​เชื่อ​ข้อความ​ที่​เขียน​ไว้​เมื่อ​สาม​ปี​ก่อน

หลาย​ข้อ​ใน​คอร์ส​นี้​กลับ​ด้าน​ไป​จาก​ที่​ผม​เขียน​ไว้​ตอน​แรก หลัง​จาก​รัน​แล้ว · StructuredTaskScope ที่​คิด​ว่า​นิ่ง​แล้ว ยัง​เป็น preview · Gatherers กับ ScopedValue ที่​คิด​ว่า​ยัง preview กลับ final แล้ว · และ switch เหนือ enum ที่​คิด​ว่า​แดง กลับ​เขียว​สนิท​ใน​รูป​หนึ่ง

นั่น​คือ​เหตุผล​ที่​ทุก​บท​มี​คำ​สั่ง​ให้​คุณ​รัน​เอง ไม่ใช่​แค่​ตัวเลข​ให้​อ่าน


🔗 อ้างอิง​ต้นทาง​ของ​บท​นี้

บท​นี้​ไม่​ได้​เพิ่ม​ข้อ​อ้าง​ใหม่ · มัน​เรียง​ผล​ของ​เจ็ด​บท​ก่อน​หน้า

  • ทุก​ตัวเลข​ใน​คอร์ส​นี้​รัน​ซ้ำ​ได้​ด้วย npm run verify:java-modern · วัด​เมื่อ 2026-09-01 บน openjdk 25.0.4.1 2026-08-18
  • JEP 12 — Preview Features (เข้า​ถึง 2026-09-01) — สถานะ​และ​กติกา​ที่​ใช้​กับ​ทุก feature ที่​ยัง​ไม่ final
  • MatchException (เข้า​ถึง 2026-09-01) — กรณี​ที่​ชนิด​ลูก​ถูก​เพิ่ม​หลัง​จาก​ผู้​เรียก​ถูก​แปล​ไป​แล้ว

เช็กความเข้าใจ — บทที่ 8

ข้อ 1 / 3

ในลำดับของบทนี้ ของอันดับที่ 3 คือ record pattern · มันต่างจากสองอันดับแรกตรงไหน