เมื่อเขียนโปรแกรม เรามักจะพบกับความจำเป็นในการจำกัดชุดของค่าที่ถูกต้องสำหรับประเภทข้อมูลบางประเภท ตัวอย่างเช่น วันในสัปดาห์สามารถมีได้ 7 ค่าที่แตกต่างกัน เดือนของปีสามารถมีได้ 12 ค่า และฤดูกาลสามารถมีได้ 4 ค่า เพื่อแก้ไขปัญหาดังกล่าว ภาษาโปรแกรมที่พิมพ์แบบคงที่จำนวนมากจะมีประเภทข้อมูลพิเศษ - การแจงนับ (
สมาชิก Enum เป็นอินสแตนซ์
องค์ประกอบ
เหมือนกัน แต่มีความหลากหลาย:
ตัวอย่างสุดท้ายแสดงให้เห็นถึงการใช้การสืบทอดใน
ประกาศการแจงนับ
enum) การแจงนับไม่ปรากฏใน Java ทันที มีการแนะนำ โครงสร้างภาษาพิเศษenumโดยเริ่มจากเวอร์ชัน 1.5 เมื่อถึงจุดนี้ โปรแกรมเมอร์ได้ใช้วิธีการอื่นในการแจงนับ การก่อสร้างแจงนับ
เริ่มต้นด้วยตัวอย่าง เรามาอธิบายenumประเภทข้อมูลสำหรับจัดเก็บฤดูกาลโดยใช้:
enum Season { WINTER, SPRING, SUMMER, AUTUMN } ตัวอย่างการใช้งานง่ายๆ:
Season season = Season.SPRING;
if (season == Season.SPRING) season = Season.SUMMER;
System.out.println(season); ด้วยเหตุนี้SUMMER จะถูก พิมพ์ ลงบนคอนโซล ฉันคิดว่าตัวอย่างชัดเจนและไม่ต้องการคำอธิบาย
เอนัมคือคลาส
โดยการประกาศenumเราจะสร้างคลาสที่ได้รับมาjava.lang.Enumจาก โดยทั่วไปการก่อสร้างenum Season { ... }จะเทียบเท่าclass Season extends java.lang.Enum { ... }กับ และถึงแม้ว่าคอมไพลเลอร์จะไม่อนุญาตให้เราสืบทอดจากjava.lang.Enumเราอย่างชัดเจน แต่ก็ยังง่ายต่อการตรวจสอบว่าenumมันได้รับการสืบทอดโดยใช้reflection:
System.out.println(Season.class.getSuperclass());สิ่งต่อไปนี้จะปรากฏบนคอนโซล:
class java.lang.Enum การสืบทอดที่แท้จริงจะดำเนินการโดยอัตโนมัติสำหรับเราโดยคอมไพเลอร์ Java ต่อไป เรามาตกลงที่จะเรียกคลาสที่สร้างโดยคอมไพเลอร์เพื่อใช้การแจงนับ - enumคลาส และค่าที่เป็นไปได้ของประเภทที่แจกแจงเป็นenumองค์ประกอบ -a
สมาชิก Enum เป็นอินสแตนซ์enumของคลาสที่สามารถเข้าถึงได้แบบคงที่
องค์ประกอบenum Season (WINTER, SPRING и т.д.)เป็นอินสแตนซ์ที่เข้าถึงได้แบบคงที่ของenum-class Seasonความพร้อมใช้งานคงที่ช่วยให้เราทำการเปรียบเทียบโดยใช้ตัวดำเนินการเปรียบเทียบ==อ้างอิง ตัวอย่าง:
Season season = Season.SUMMER;
if (season == Season.AUTUMN) season = Season.WINTER;
ชื่อและหมายเลขลำดับขององค์ประกอบแจงนับ
ตามที่กล่าวไว้ก่อนหน้านี้enum-class ใด ๆ สืบทอดjava.lang.Enumซึ่งมีหลายวิธีที่เป็นประโยชน์สำหรับการแจงนับทั้งหมด ตัวอย่าง:
Season season = Season.WINTER;
System.out.println("season.name()=" + season.name() + " season.toString()=" + season.toString() + " season.ordinal()=" + season.ordinal()); ผลลัพธ์จะเป็น:
season.name()=WINTER season.toString()=WINTER season.ordinal()=0 วิธีการต่างๆname()และ แสดง ไว้ ที่ toString()นี่ ordinal()ความหมายของวิธีการต่างๆ นั้นชัดเจน ควรสังเกตว่าวิธีการเหล่านี้สืบทอด enumมาจากคลาส การรับองค์ประกอบโดยการแสดงสตริงของชื่อบ่อยครั้งงานเกิดขึ้นจากการรับองค์ประกอบด้วยการแสดงสตริง เพื่อวัตถุประสงค์เหล่านี้ ในแต่ละ-class คอมไพลเลอร์จะสร้างวิธีสแตติกพิเศษโดยอัตโนมัติ: ซึ่งส่งคืนองค์ประกอบการแจงนับที่มีชื่อเท่ากับ ตัวอย่างการใช้งาน: java.lang.Enumenumenumenumpublic static EnumClass valueOf(String name)EnumClassname
String name = "WINTER";
Season season = Season.valueOf(name); จากการรันโค้ด ตัวแปรซีซันจะSeason.WINTERเท่ากับ โปรดทราบว่าหากไม่พบองค์ประกอบIllegalArgumentException จะถูกส่งออกไป และหากมีค่าเท่าnameกันNullPointerException จะถูกโยนทิ้ง โดยวิธีการนี้มักจะถูกลืม ด้วยเหตุผลบางประการ หลายๆ คนเชื่อมั่นอย่างยิ่งว่าหากฟังก์ชันรับหนึ่งอาร์กิวเมนต์และภายใต้เงื่อนไขบางประการได้ส่งIllegalArgumentException จากนั้นเมื่อส่งผ่านที่นั่นIllegalArgumentExceptionก็จะถูกโยนด้วยเช่นกัน แต่นั่นอยู่นอกประเด็น มาต่อกัน การรับองค์ประกอบทั้งหมดของการแจงนับ บางครั้งคุณจำเป็นต้องได้รับรายการองค์ประกอบทั้งหมดของ -คลาส ณ รันไทม์ เพื่อวัตถุประสงค์เหล่านี้คอมไพลเลอร์จะสร้างเมธอดในแต่ละ -class ตัวอย่างการใช้งาน: nullnullenumenumpublic static EnumClass[] values()
System.out.println(Arrays.toString(Season.values())); เราได้รับผลลัพธ์:
[WINTER, SPRING, SUMMER, AUTUMN] โปรดทราบว่าไม่มีการกำหนดวิธีการvalueOf()หรือวิธีการvalues()ในชั้นjava.lang.Enumเรียน แต่จะถูกเพิ่มโดยอัตโนมัติโดยคอมไพเลอร์เมื่อenumมีการคอมไพล์ -class การเพิ่มวิธีการของคุณเองในenum-class คุณมีโอกาสที่จะเพิ่มวิธีการของคุณเองทั้งในenum-class และองค์ประกอบ:
เหมือนกัน แต่มีความหลากหลาย:
ตัวอย่างสุดท้ายแสดงให้เห็นถึงการใช้การสืบทอดในenum. เพิ่มเติมเกี่ยวกับเรื่องนี้ในภายหลัง การสืบทอดenum ใน Java enumช่วยให้คุณสามารถใช้ลำดับชั้นของคลาสได้ ซึ่งอ็อบเจ็กต์ของคลาสนั้นถูกสร้างขึ้นในอินสแตนซ์เดียวและสามารถเข้าถึงได้แบบคงที่ ในกรณีนี้ องค์ประกอบenumสามารถมีตัวสร้างของตัวเองได้ ยกตัวอย่าง: ที่ นี่เรา
ประกาศการแจงนับTypeด้วยสามองค์ประกอบINTและ คอมไพเลอร์จะสร้างคลาสและอ็อบเจ็กต์ต่อไปนี้: INTEGERSTRING
Type- คลาสที่ได้มาจากjava.lang.EnumINT— วัตถุของคลาสที่ 1 ที่ได้มาจากTypeINTEGER— วัตถุของคลาสที่ 2 ที่ได้มาจากTypeSTRING— วัตถุชั้นที่ 3 ที่ได้มาจากType
Object parse(String)และตัวสร้าง Type(..., boolean)ในเวลาเดียวกันวัตถุของคลาสINTและมีอยู่ในสำเนาเดียวและสามารถเข้าถึงได้แบบคงINTEGERที่ STRINGคุณสามารถตรวจสอบสิ่งนี้ได้:
System.out.println(Type.class);
System.out.println(Type.INT.getClass() + " " + Type.INT.getClass().getSuperclass());
System.out.println(Type.INTEGER.getClass() + " " + Type.INTEGER.getClass().getSuperclass());
System.out.println(Type.STRING.getClass() + " " + Type.STRING.getClass().getSuperclass());เราได้รับผลลัพธ์:
class Type
class Type$1 class Type
class Type$2 class Type
class Type$3 class Type จะเห็นได้ว่าคอมไพเลอร์สร้างคลาสขึ้นมา 1 คลาสTypeและคลาส 3 nestedคลาสที่ได้มาจากType.
ถอดรหัสคลาส enum พร้อมการสืบทอด
เพื่อยืนยันข้างต้น เรายังนำเสนอผลลัพธ์ของการถอดรหัสการแจงนับTypeจากตัวอย่างด้านบน:
การแจงนับและพหุสัณฐานแบบพาราเมตริก
ผู้อ่านอาจสงสัยว่า: " เหตุใดการแจงนับประเภทข้างต้นจึงไม่ใช้ยาชื่อสามัญ "enumความจริงก็คือว่าใน Java ห้ามใช้ยาชื่อสามัญ ดังนั้นตัวอย่างต่อไปนี้จะไม่คอมไพล์:
enum Type<T> {}
การศึกษาต่อ
เพื่อความเข้าใจที่ลึกซึ้งยิ่งขึ้นเกี่ยวกับวิธีการทำงานของการแจงนับใน Java ฉันขอแนะนำให้คุณทำความคุ้นเคยกับซอร์สโค้ดของคลาสjava.lang.Enumและใช้ตัวถอดรหัส Jad เพื่อศึกษาโค้ดที่สร้างขึ้น นอกจากนี้ การศึกษาซอร์สโค้ดไลบรารี Java จำเป็นอย่างยิ่งในการทำความเข้าใจว่ากลไกต่างๆ ใน Java ทำงานกี่กลไก และมีประโยชน์ในการอ้างอิงสำหรับการออกแบบเชิงวัตถุ ลิงก์ไปยังแหล่งที่มาดั้งเดิม: http://alexander.lds.lg.ua/
GO TO FULL VERSION