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

switch ที่​ไม่มี default มี default อยู่ และ​มัน​โยน exception ที่​คุณ​ไม่​เคย​พิมพ์

คุณ​เขียน switch ที่​ครอบคลุม​ทุก​ค่า​ของ enum แล้ว​ไม่​ใส่ default

javac ไม่​บ่น เพราะ​มัน​พิสูจน์​ได้​ว่า​คุณ​ครอบคลุม​ครบ​จริง · นั่น​คือ​ทั้งหมด​ที่​มัน​รู้ ณ ตอน​ที่​แปล

library หนึ่ง​ตัว สอง​รุ่น · รุ่น​แรก​มี 2 ค่า รุ่น​สอง​มี 3 ค่า เพิ่ม​มา​ค่า​เดียว​คือ BLUE

ผู้​เรียก​ถูก​แปล ครั้ง​เดียว เทียบ​กับ​รุ่น​แรก แล้ว​ไม่​ถูก​แตะ​อีก​เลย

library บน classpathREDBLUE
รุ่น​แรก · 2 ค่าokIllegalArgumentException
รุ่น​สอง · 3 ค่าokMatchException

MatchException ไม่​ได้​อยู่​ใน​ซอร์ส​ของ​ผู้​เรียก​เลย ไม่มี​ใคร​พิมพ์​คำ​นั้น ไม่มี throw ไม่มี default

sha ของ file .class ก่อน​การ​ทดลอง​คือ 31c741d3dbd629d7 และ​หลัง​การ​ทดลอง​คือ 31c741d3dbd629d7 · ไม่มี​ไบต์​ไหน​ขยับ

ตาราง​นี้​ถูก​วาง​ให้​พิสูจน์​ตัว​เอง​ได้ ก่อน​จะ​พิสูจน์​อะไร​ให้​คุณ

ช่องผลมัน​ตัด​คำ​อธิบาย​ไหน​ทิ้ง
รุ่น​แรก · REDokตัด “การ​ทดลอง​พัง​ตั้งแต่​ต้น”
รุ่น​แรก · BLUEIllegalArgumentExceptionตัด “classpath ไม่​เคย​เปลี่ยน​จริง” — รุ่น​แรก​ไม่มี​ค่า​ชื่อ​นี้​ให้หา​เจอ
รุ่น​สอง · REDokตัด “รุ่น​สอง​พัง​ทั้ง​ใบ”

ถ้า​ไม่มี​สาม​ช่อง​นี้ ช่อง​ที่​สี่​พิสูจน์​อะไร​ไม่​ได้​เลย

javac ตรวจ​ความ​ครอบคลุม​ของ switch ตอน​แปล · ตอน​นั้น​มัน​เห็น library รุ่น​แรก และ​มัน​ถูก​ต้อง​ตาม​ข้อมูล​ที่​มี

แต่ bytecode ที่​มัน​คาย​ออก​มา​ต้อง​อยู่​รอด​ใน​โลก​ที่ library เปลี่ยน​ได้ · Java ยอม​ให้​คุณ สลับ jar โดย​ไม่​แปล​ผู้​เรียก​ใหม่ นั่น​คือ​ทั้ง​จุด​ขาย​และ​ต้น​เหตุ

ถ้า​ไม่มี​ทางออก​นั้น switch จะ​ไหล​ทะลุ​ไป​เจอ อะไร​ก็​ไม่รู้ — คืน​ค่า​ขยะ หรือ​กระโดด​ผิด​ที่ · javac จึง​ปิด​รู​ด้วย​การ​โยน exception ชนิด​หนึ่ง​ที่​บอก​ว่า “ค่าที่​ได้ ไม่​ตรง​กับ​รูป​แบบ​ไหน​เลย​ที่​รู้จัก​ตอน​แปล”

ความ​ครอบคลุม​เป็น​ข้อ​สรุป​ที่​มี​วัน​หมด​อายุ

switch ที่​ไม่มี default ไม่​ได้​แปล​ว่า “ทุก​ค่า​ถูก​จัดการ” · มัน​แปล​ว่า “ทุก​ค่าที่​มี​อยู่​ตอน​แปล ถูก​จัดการ”

ประโยค​ที่​สอง​อ่อน​กว่า​ประโยค​แรก​มาก และ​ความ​ต่าง​จะ​โผล่​ก็​ต่อ​เมื่อ​มี​คน​อัปเดต dependency · ซึ่ง​เป็น​ตอน​ที่​ไม่มี​ใคร​กำลัง​มอง code ชิ้น​นี้​อยู่

ตัวอย่าง​ข้าง​บน​เป็น enum ธรรมดา ไม่มี sealed ไม่มี pattern · และ​มัน​ก็​ยัง​โยน

สิ่ง​ที่​จุด​ชนวน​คือ javac พิสูจน์​ความ​ครอบคลุม​ให้​ได้ โดยที่​คุณ​ไม่​ได้​เขียน default · เมื่อไร​ที่​เงื่อนไข​นั้น​เป็น​จริง ทางออก​สังเคราะห์​จะ​ถูก​ใส่​เข้า​มา

ตัว​วัด​ของ​หน้า​นี้​พิสูจน์​ทิศ​ตรง​ข้าม​ไว้​ด้วย · มี file ฝาแฝด​ที่​เหมือน​กัน​ทุก​อย่าง ยกเว้น​มี default · bytecode ของ​มัน​มี​ทางออก​สังเคราะห์​ไหม คำ​ตอบ​คือ ไม่มี และ​มัน​รอด​ทุก​ช่อง​ของ​ตาราง

ตอน​แปล javac ปฏิเสธ switch ที่​ไม่​ครอบคลุม​จริง ๆ · ตัว​วัด​มี file ที่​จงใจ​ขาด case และ javac คืน​รหัส 1 พร้อม compiler.err.not.exhaustive

แต่​นั่น​คือ​คำ​เตือน​สำหรับ code ที่​ไม่​ครอบคลุม​ตอน​นี้ ไม่ใช่​คำ​เตือน​สำหรับ code ที่​ครอบคลุม​ตอน​นี้​และ​จะ​ไม่​ครอบคลุม​พรุ่ง​นี้

ไม่มี​สวิตช์​ไหน​บอก​คุณ​ว่า switch ตัว​นี้​จะ​พัง​ถ้า dependency เพิ่ม​ค่า เพราะ​ตอน​แปล ข้อมูล​นั้น​ยัง​ไม่มี​อยู่​บน​โลก

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

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

สิ่ง​ที่​หน้า​นี้​ไม่​ได้​บอก​ว่า​ให้​ทำ

หน้า​นี้​ไม่​ได้​บอก​ให้​ใส่ default ทุก​ที่ · การ​ใส่ default ใน​กรณี​แรก​ทำให้​เสีย​การ​ตรวจ ที่​มี​ค่าที่​สุด​ของ javac ไป และ​เปลี่ยน “แดง​ตอน​แปล” เป็น “เงียบ​ตอน​รัน”

คำถาม​ที่​ต้อง​ตอบ​ก่อน​คือ ใคร​คุม enum ตัว​นี้ ไม่ใช่ “ควร​ใส่ default ไหม”

  • ไม่​ได้​วัด​เวลา หน่วย​ของ​หน้า​นี้​คือ​ชื่อ class ของ exception, รหัส​ออก​ของ javac และ sha ของ file .class · ทั้ง​สาม​ข้าม​เครื่อง​ได้
  • ไม่​ได้​วัด JDK ที่​เก่า​กว่า 21 exception ตัว​นี้​เข้า​มา​ที่ 21 · วัด​บน 21, 25, 26 และ​ได้​ผล​เดียวกัน​ทั้ง​สาม​ตัว
  • ไม่​ได้​วัด​คอม​ไพ​เลอ​ร์​ตัว​อื่น ecj ของ Eclipse อาจ​คาย bytecode คนละ​แบบ
  • ไม่​ได้​วัด​กรณี​ที่​ค่า​ใหม่​ถูก​ลบ ไม่ใช่​ถูก​เพิ่ม ซึ่ง​พัง​คนละ​แบบ

ตัว​วัด​อยู่​ที่ scripts/synthetic-default/ รัน​ด้วย npm run verify:synthetic-default · มัน​อยู่​ใน​เกต​ของ CI จึง​มี​คน​รัน​ทุก​ครั้ง​ที่​มี​คน push

ซอร์ส​ของ​ตัว​วัด​ไม่มี​คำ​นั้น​เลย และ​มี​ด่าน​บังคับ​ไว้

ข้อ​อ้าง​ทั้ง​หน้า​พิง​อยู่​บน​ประโยค​เดียว: คำ​ว่า MatchException ไม่​ได้​ถูก​พิมพ์​ลง​ใน code · ด่าน​ของ CI ถอด​คอม​เมน​ต์​ออก​จาก​ซอร์ส​ของ​ผู้​เรียก​แล้ว​ตรวจ​ว่า​ไม่มี​คำ​นั้น​จริง วัด​ได้ ไม่มี

ตัว​ถอด​คอม​เมน​ต์​เอง​ก็​มี​ช่อง​ควบคุม เพราะ​ถ้า​มัน​ถอด code ทิ้ง​ไป​ด้วย ข้อ​ข้าง​บน​จะ​เป็น​จริง โดย​บังเอิญ · ด่าน​จึง​บังคับ​ว่า​หลัง​ถอด​แล้ว ต้อง​ยัง​เหลือ switch และ case อยู่​ใน​มือ