มีวิธีค่าในการแจกแจงที่ใช้ในการสร้างอาร์เรย์ตามลำดับที่กำหนดโดยการแจงนับซึ่งสามารถใช้เพื่อสำรวจได้ คลาสการแจงนับที่กำหนดเองของเราทั้งหมดสืบทอดมาจาก java.lang.Enum และมีฟังก์ชันต่อไปนี้ในตัวอย่าง:
คัดลอกรหัสรหัส ดังต่อไปนี้:
//: แจกแจง/EnumClass.java
// ความสามารถของคลาส Enum
นำเข้า net.mindview.util.Print.*;
พุ่มไม้ enum { พื้น, คลาน, แขวน }
EnumClass คลาสสาธารณะ {
โมฆะคงที่สาธารณะ main (String [] args) {
สำหรับ (พุ่มไม้ s : Shrubbery.values()) {
พิมพ์ (s + "ลำดับ:" + s.ordinal());
printnb (s.compareTo (พุ่มไม้รวบรวมข้อมูล) + " ");
printnb (s.equals (ไม้พุ่ม. CRAWLING) + " ");
พิมพ์ (s == Shrubbery.CRAWLING);
พิมพ์(s.getDeclaringClass());
พิมพ์(s.ชื่อ());
พิมพ์("----------------------");
-
// สร้างค่าแจงนับจากชื่อสตริง:
สำหรับ (String s: "HANGING CRAWLING GROUND".split(" ")) {
ไม้พุ่มไม้พุ่ม = Enum.valueOf (Shrubbery.class, s);
พิมพ์ (ไม้พุ่ม);
-
-
} /* เอาต์พุต:
ลำดับกราวด์: 0
-1 เท็จ เท็จ
คลาสไม้พุ่ม
Joshua Bloch มีประโยชน์อย่างมากในการพัฒนาบทนี้
พื้น
-
ลำดับการรวบรวมข้อมูล: 1
จริงจริง
คลาสไม้พุ่ม
คลาน
-
ลำดับแขวน: 2
เท็จเท็จ
คลาสไม้พุ่ม
แขวนอยู่
-
แขวนอยู่
คลาน
พื้น
-
เรายังสามารถใช้การอ้างอิงการแจงนับแบบคงที่ได้:
คัดลอกรหัสรหัส ดังต่อไปนี้:
//: แจกแจง/Spiciness.java
แจกแจงแพ็คเกจ;
ความเผ็ดร้อนสาธารณะ {NOT, MILD, MEDIUM, HOT, FLAMING} ///:~
//: แจกแจง/Burrito.java
แจกแจงแพ็คเกจ;
นำเข้าแจกแจงคงความเผ็ด.*;
Burrito คลาสสาธารณะ {
ระดับความเผ็ด;
Burrito สาธารณะ (ระดับความเผ็ด) { this.degree = องศา;}
สตริงสาธารณะ toString () { กลับ "Burrito คือ "+ องศา;}
โมฆะคงที่สาธารณะ main (String [] args) {
System.out.println (เบอร์ริโตใหม่ (ไม่ใช่));
System.out.println (เบอร์ริโตใหม่ (ขนาดกลาง));
System.out.println (เบอร์ริโตใหม่ (ร้อน));
-
} /* เอาต์พุต:
เบอร์ริโตไม่ใช่
เบอร์ริโตมีขนาดกลาง
เบอร์ริโตร้อน
-
นอกเหนือจากการเพิ่มวิธีการในการแจงนับซึ่งไม่สามารถสืบทอดมาได้ การแจงนับยังสามารถใช้เป็นคลาสทั่วไปได้ ซึ่งหมายความว่าคุณสามารถเพิ่มวิธีการในการแจงนับได้ และคุณยังสามารถกำหนดวิธีการหลักในการแจงนับได้ด้วย:
คัดลอกรหัสรหัส ดังต่อไปนี้:
//: แจกแจง/OzWitch.java
// แม่มดในดินแดนออซ
นำเข้า net.mindview.util.Print.*;
สาธารณะ enum OzWitch {
// ต้องกำหนดอินสแตนซ์ก่อน ก่อนวิธีการ:
WEST("Miss Gulch หรือที่รู้จักในชื่อแม่มดชั่วร้ายแห่งทิศตะวันตก"),NORTH("กลินดา แม่มดผู้ใจดีแห่งทิศเหนือ"),EAST("แม่มดชั่วร้ายแห่งตะวันออก ผู้สวมใส่ทับทิม " + "รองเท้าแตะถูกบดขยี้โดย บ้านของโดโรธี"),SOUTH("ดีโดยการอนุมาน แต่ขาดหายไป");
คำอธิบายสตริงส่วนตัว
// Constructor ต้องเป็นแพ็คเกจหรือการเข้าถึงแบบส่วนตัว:
OzWitch ส่วนตัว (คำอธิบายสตริง) {
this.description = คำอธิบาย;
-
สตริงสาธารณะ getDescription() { คำอธิบายการส่งคืน }
โมฆะคงที่สาธารณะ main (String [] args) {
สำหรับ (แม่มด OzWitch : OzWitch.values())
พิมพ์ (แม่มด + `: " + Witch.getDescription());
-
} /* เอาต์พุต:
ตะวันตก: คุณกัลช์ หรือที่รู้จักในชื่อแม่มดชั่วร้ายแห่งทิศตะวันตก
ทิศเหนือ: กลินดา แม่มดผู้ใจดีแห่งแดนเหนือ
ตะวันออก: แม่มดชั่วร้ายแห่งตะวันออก ผู้สวมรองเท้าแตะทับทิม ถูกบ้านของโดโรธีบดขยี้
ใต้: ดีโดยการอนุมาน แต่ขาดไป
-
คัดลอกรหัสรหัส ดังต่อไปนี้:
//: แจกแจง/SpaceShip.java
ยานอวกาศ enum สาธารณะ {
ลูกเสือ, สินค้า, การขนส่ง, เรือลาดตระเวน, เรือรบ, มารดา;
สตริงสาธารณะ toString() {
รหัสสตริง = ชื่อ ();
สตริงที่ต่ำกว่า = id.substring(1).toLowerCase();
กลับ id.charAt(0) + ต่ำกว่า;
-
โมฆะคงที่สาธารณะ main (String [] args) {
สำหรับ (ยานอวกาศ s : ค่า ()) {
System.out.println(s);
-
-
} /* เอาต์พุต:
ลูกเสือ
สินค้า
ขนส่ง
ครุยเซอร์
เรือรบ
ยานแม่
-
การแจงนับในคำสั่ง switch บทบาทสำคัญของการแจงนับอยู่ในคำสั่ง switch โดยปกติแล้วคำสั่ง switch จะใช้ได้กับค่าจำนวนเต็มเท่านั้น แต่มีลำดับจำนวนเต็มในตัวในการแจงนับ ดังนั้น ลำดับของอินสแตนซ์จึงสามารถกำหนดได้ด้วยวิธีการบางอย่าง ดังนั้น enums จึงสามารถใช้ในคำสั่ง switch ได้:
คัดลอกรหัสรหัส ดังต่อไปนี้:
//: แจกแจง/TrafficLight.java
// แจงนับในคำสั่ง switch
นำเข้า net.mindview.util.Print.*;
// กำหนดประเภท enum:
สัญญาณ enum { สีเขียว สีเหลือง สีแดง }
TrafficLight ระดับสาธารณะ {
สีของสัญญาณ = Signal.RED;
การเปลี่ยนแปลงโมฆะสาธารณะ () {
สวิตช์ (สี) {
// โปรดทราบว่าคุณไม่จำเป็นต้องพูด Signal.RED
// ในคำสั่ง case:
กรณีสีแดง: สี = สัญญาณสีเขียว;
หยุดพัก;
กรณีสีเขียว: สี = สัญญาณสีเหลือง;
หยุดพัก;
กรณีสีเหลือง: สี = สัญญาณสีแดง;
หยุดพัก;
-
-
สตริงสาธารณะ toString() {
กลับ "สัญญาณไฟจราจรคือ" + สี;
-
โมฆะคงที่สาธารณะ main (String [] args) {
TrafficLight t = TrafficLight ใหม่ ();
สำหรับ (int i = 0; i < 7; i ++) {
พิมพ์(t);
t.เปลี่ยน();
-
-
} /* เอาต์พุต:
สัญญาณไฟจราจรเป็นสีแดง
สัญญาณไฟจราจรเป็นสีเขียว
สัญญาณไฟจราจรเป็นสีเหลือง
สัญญาณไฟจราจรเป็นสีแดง
สัญญาณไฟจราจรเป็นสีเขียว
สัญญาณไฟจราจรเป็นสีเหลือง
สัญญาณไฟจราจรเป็นสีแดง
-
ความลับของค่า() แม้ว่าเราจะเคยใช้วิธีค่านิยมมาก่อน แต่ถ้าเราดูที่ Enum เราก็ไม่พบวิธีค่านิยม แล้วยังมีวิธีอื่นที่ซ่อนอยู่อีกหรือไม่ เราสามารถตรวจสอบได้โดยใช้โค้ดสะท้อนง่ายๆ:
คัดลอกรหัสรหัส ดังต่อไปนี้:
//: แจกแจง/Reflection.java
// การวิเคราะห์แจงนับโดยใช้การสะท้อนกลับ
นำเข้า java.lang.reflect.*;
นำเข้า java.util.*;
นำเข้า net.mindview.util.*;
นำเข้า net.mindview.util.Print.*;
enum สำรวจ { ที่นี่ ที่นั่น }
การสะท้อนระดับสาธารณะ {
ชุดสาธารณะ <String> วิเคราะห์ (คลาส <?> enumClass) {
print("----- กำลังวิเคราะห์ " + enumClass + " -----");
พิมพ์("อินเทอร์เฟซ:");
สำหรับ (ประเภท t : enumClass.getGenericInterfaces())
พิมพ์(t);
พิมพ์("ฐาน: " + enumClass.getSuperclass());
พิมพ์("วิธีการ: ");
Set<String> method = new TreeSet<String>();
สำหรับ (วิธีการ m : enumClass.getMethods())
วิธีการเพิ่ม(m.getName());
พิมพ์(วิธีการ);
วิธีการส่งคืน;
-
โมฆะคงที่สาธารณะ main (String [] args) {
ตั้งค่า exploreMethods = วิเคราะห์ (Explore.class);
ตั้งค่า <String> enumMethods = วิเคราะห์ (Enum.class);
พิมพ์ ("Explore.containsAll (Enum)? " +
exploreMethods.containsAll (enumMethods));
printnb("Explore.removeAll(Enum): ");
exploreMethods.removeAll (enumMethods);
พิมพ์ (สำรวจวิธีการ);
// ถอดรหัสโค้ดสำหรับ enum:
OSExecute.command("javap สำรวจ");
-
} /* เอาต์พุต:
----- วิเคราะห์คลาส สำรวจ -----
อินเทอร์เฟซ:
ฐาน: คลาส java.lang.Enum
วิธีการ:
[compareTo, เท่ากับ, getClass, getDeclaringClass, hashCode, ชื่อ, แจ้งเตือน, notifyAll, ลำดับ, toString, valueOf, ค่า, รอ]
----- กำลังวิเคราะห์คลาส java.lang.Enum -----
อินเทอร์เฟซ:
java.lang.เปรียบเทียบได้<E>
อินเทอร์เฟซ java.io.Serializable
ฐาน: คลาส java.lang.Object
วิธีการ:
[compareTo, เท่ากับ, getClass, getDeclaringClass, hashCode, ชื่อ, แจ้งเตือน, notifyAll, ลำดับ, toString, valueOf, รอ]
Explore.containsAll(Enum) จริงหรือไม่
Explore.removeAll(Enum): [ค่า]
เรียบเรียงจาก "Reflection.java"
คลาสสุดท้าย Explore ขยาย java.lang.Enum {
สาธารณะคงสุดท้าย สำรวจที่นี่;
สาธารณะคงสุดท้าย สำรวจที่นั่น;
สาธารณะคงที่สุดท้ายสำรวจค่า [] ();
สาธารณะคงที่สำรวจ valueOf (java.lang.String);
คงที่ {};
-
-
เราจะเห็นว่าคอมไพเลอร์เพิ่มวิธีการค่า เมธอด valueOf จะถูกเพิ่มโดยคอมไพเลอร์เมื่อสร้างการแจงนับ แต่ก็มีเมธอด valueOf ในคลาส Enum ด้วย แต่เมธอดนี้มีพารามิเตอร์สองตัว ในขณะที่เมธอด valueOf ที่เพิ่มโดยคอมไพเลอร์มีเพียงพารามิเตอร์เดียวเท่านั้น การแจกแจงจะถูกตีความว่าเป็นขั้นสุดท้ายโดยคอมไพเลอร์ ดังนั้นการแจงนับจึงไม่สามารถสืบทอดได้ เนื่องจากวิธีการค่าเป็นวิธีการคงที่ที่คอมไพเลอร์เพิ่มไว้ หากคุณส่งการแจงนับไปยัง Enum วิธีการค่าจะไม่สามารถใช้ได้ แต่มีวิธีการ getEnumConstants ใน Class ดังนั้นแม้ว่าวิธีการค่าจะเป็น ไม่พร้อมใช้งานใน Enum แต่คุณยังสามารถรับอินสแตนซ์การแจงนับผ่านวัตถุ Class:
คัดลอกรหัสรหัส ดังต่อไปนี้:
//: แจงนับ/UpcastEnum.java
// ไม่มีค่า () วิธีการถ้าคุณอัพแคสต์ enum
ค้นหา enum { ที่นี่, YON }
UpcastEnum คลาสสาธารณะ {
โมฆะคงที่สาธารณะ main (String [] args) {
ค้นหา [] vals = Search.values ();
Enum e = ค้นหาที่นี่; // Upcast
// e.values(); // ไม่มีค่า () ใน Enum
สำหรับ(Enum en : e.getClass().getEnumConstants())
System.out.println(en);
-
} /* เอาต์พุต:
ที่นี่
ยอน
-
การใช้งานโดยไม่มีการสืบทอด เนื่องจากประเภทการแจงนับที่เรากำหนดให้สืบทอดทั้งหมดจาก java.lang.Enum และ Java ไม่รองรับการสืบทอดหลายรายการ ดังนั้นการแจงนับจึงไม่ถูกสร้างขึ้นผ่านการสืบทอด แต่การแจงนับสามารถสร้างได้โดยการสืบทอดอินเทอร์เฟซตั้งแต่หนึ่งอินเทอร์เฟซขึ้นไป:
คัดลอกรหัสรหัส ดังต่อไปนี้:
//: แจกแจง/การ์ตูน/EnumImplementation.java
// enum สามารถใช้อินเทอร์เฟซได้
แพ็คเกจแจกแจงการ์ตูน;
นำเข้า java.util.*;
นำเข้า net.mindview.util.*;
enum CartoonCharacter ใช้ Generator< CartoonCharacter> {
SLAPPY, SPANKY, PUNCHY, SILLY, BOUNCY, NUTTY, BOB;
แรนด์สุ่มส่วนตัว = สุ่มใหม่ (47);
CartoonCharacter สาธารณะต่อไป () {
ส่งกลับค่า()[rand.nextInt(ค่า().ความยาว)];
-
-
EnumImplementation ระดับสาธารณะ {
สาธารณะคง <T> เป็นโมฆะ printNext (เครื่องกำเนิดไฟฟ้า <T> rg) {
System.out.print(rg.next() + ", ");
-
โมฆะคงที่สาธารณะ main (String [] args) {
// เลือกอินสแตนซ์ใดก็ได้:
CartoonCharacter cc = CartoonCharacter.BOB;
สำหรับ(int i = 0; i < 10; i++)
printNext(ซีซี);
-
} /* เอาต์พุต:
บ๊อบ, พันช์, บ๊อบ, SPANKY, นัตตี้, พันช์, หละหลวม, บ้าบิ่น, บ้าบิ่น, หละหลวม,
-
การเลือกแบบสุ่ม ในหลายๆ ตัวอย่างของเราในภายหลัง เราจะสุ่มเลือกอ็อบเจ็กต์จากอินสแตนซ์การแจงนับ เราสร้างคลาสสาธารณะเพื่อใช้สิ่งนี้:
คัดลอกรหัสรหัส ดังต่อไปนี้:
//: net/mindview/util/Enums.java
แพ็คเกจ net.mindview.util;
นำเข้า java.util.*;
Enums คลาสสาธารณะ {
แรนด์สุ่มคงที่ส่วนตัว = สุ่มใหม่ (47);
สาธารณะคงที่ <T ขยาย Enum <T>> T สุ่ม (Class <T> ec) {
กลับสุ่ม(ec.getEnumConstants());
-
สาธารณะคงที่ <T> T สุ่ม (ค่า T []) {
ส่งคืนค่า [rand.nextInt (values.length)];
-
-
คัดลอกรหัสรหัส ดังต่อไปนี้:
//: แจงนับ/RandomTest.java
นำเข้า net.mindview.util.*;
กิจกรรม enum { นั่ง นอน ยืน กระโดด วิ่ง หลบ กระโดด ล้ม บิน }
RandomTest คลาสสาธารณะ {
โมฆะคงที่สาธารณะ main (String [] args) {
สำหรับ(int i = 0; i < 20; i++)
System.out.print(Enums.random(Activity.class) + " ");
-
} /* เอาต์พุต:
ยืน บิน วิ่ง ยืน วิ่ง ยืน นอน หลบ นั่ง วิ่ง กระโดด กระโดด กระโดด วิ่ง ยืน นอน ล้ม วิ่ง บินโกหก
-
การใช้อินเทอร์เฟซเพื่อจัดระเบียบการแจงนับไม่สามารถสืบทอดได้ ซึ่งบางครั้งทำให้เราไม่สะดวก เนื่องจากบางครั้งเราต้องการขยายจำนวนการแจงนับผ่านการสืบทอด และบางครั้งเราจำเป็นต้องจัดกลุ่มการแจงนับ สำหรับอย่างหลัง เราสามารถกำหนดการแจกแจงแบบกลุ่มภายในอินเทอร์เฟซ แล้วสร้างการแจงนับโดยสืบทอดจากอินเทอร์เฟซนี้ ดังต่อไปนี้ เรามีหมวดหมู่อาหารที่แตกต่างกันที่ต้องสร้างเป็นการแจงนับ แต่เราต้องกำหนดแต่ละหมวดหมู่เป็น ประเภท ของอาหารมีดังนี้
คัดลอกรหัสรหัส ดังต่อไปนี้:
//: แจกแจง/menu/Food.java
// การจัดหมวดหมู่ย่อยของ enum ภายในอินเทอร์เฟซ
แพ็คเกจแจกแจงเมนู;
อินเทอร์เฟซสาธารณะ อาหาร {enum Appetizer ใช้อาหาร {SALAD, SOUP, SPRING_ROLLS;}
enum MainCourse ประยุกต์อาหาร {LASAGNE, BURRITO, PAD_THAI,LENTILS, HUMMOUS, VINDALOO;}
enum ของหวานนำอาหาร {TIRAMISU, GELATO, BLACK_FOREST_CAKE,FRUIT, CREME_CARAMEL;}
enum Coffee ใช้อาหาร {BLACK_COFFEE, DECAF_COFFEE, ESPRESSO,LATTE, CAPPUCCINO, TEA, HERB_TEA;}
-
เนื่องจากการแจงนับแต่ละรายการถูกกำหนดให้เป็นการนำอินเทอร์เฟซไปใช้ การแจงนับแต่ละรายการจึงเป็นประเภทอาหาร ดังนี้:
คัดลอกรหัสรหัส ดังต่อไปนี้:
//: แจกแจง/เมนู/TypeOfFood.java
แพ็คเกจแจกแจงเมนู;
นำเข้า enumerated.menu.Food.*;
TypeOfFood คลาสสาธารณะ {
โมฆะคงที่สาธารณะ main (String [] args) {
อาหาร อาหาร = Appetizer.SALAD;
อาหาร = MainCourse.LASAGNE;
อาหาร = ของหวาน เจลาโต้;
อาหาร = กาแฟคาปูชิโน;
-
-
แต่อินเทอร์เฟซไม่สามารถดำเนินการได้หลายประเภท เช่น การแจงนับ ดังนั้น หากคุณต้องการการแจงนับ คุณสามารถสรุปอินสแตนซ์ของการแจงนับแต่ละประเภทในการแจงนับได้:
คัดลอกรหัสรหัส ดังต่อไปนี้:
//: แจกแจง/menu/Course.java
แพ็คเกจแจกแจงเมนู;
นำเข้า net.mindview.util.*;
หลักสูตร enum สาธารณะ {
อาหารเรียกน้ำย่อย(Food.Appetizer.class),หลักสูตรหลัก(Food.MainCourse.class),ของหวาน(Food.Dessert.class),กาแฟ(Food.Coffee.class);
คุณค่าอาหารส่วนตัว[];
หลักสูตรส่วนตัว(ประเภท<? ขยายอาหาร>) {
ค่า = kind.getEnumConstants();
-
การสุ่มเลือกอาหารสาธารณะ () {
กลับ Enums.random (ค่า);
-
-
การแจงนับแต่ละรายการใช้คลาสอ็อบเจ็กต์เป็นพารามิเตอร์คอนสตรัคเตอร์ที่สอดคล้องกัน เราสามารถใช้ getEnumConstants จากพารามิเตอร์นี้เพื่อรับอินสแตนซ์การแจงนับสามารถใช้ในเมธอด RandomSelection เพื่อสร้างอาหารแบบสุ่ม:
คัดลอกรหัสรหัส ดังต่อไปนี้:
//: แจกแจง/menu/Meal.java
แพ็คเกจแจกแจงเมนู;
มื้ออาหารในชั้นเรียนสาธารณะ {
โมฆะคงที่สาธารณะ main (String [] args) {
สำหรับ (int i = 0; i < 5; i ++) {
for(หลักสูตรหลักสูตร : Course.values()) {
อาหาร อาหาร = course.randomSelection();
System.out.println(อาหาร);
-
System.out.println("---");
-
-
} /* เอาต์พุต:
SPRING_ROLLS
วินดาลู
ผลไม้
DECAF_กาแฟ
-
ซุป
วินดาลู
ผลไม้
ชา
-
สลัด
เบอร์ริโต้
ผลไม้
ชา
-
สลัด
เบอร์ริโต้
CREME_CARAMEL
ลาเต้
-
ซุป
เบอร์ริโต้
ทีรามิสุ
เอสเพรสโซ่
-
-
ต่อไปนี้เป็นการใช้งานที่กะทัดรัดมากขึ้น:
คัดลอกรหัสรหัส ดังต่อไปนี้:
//: แจกแจง/SecurityCategory.java
// การแบ่งหมวดหมู่ย่อยที่กระชับยิ่งขึ้นของ enum
นำเข้า net.mindview.util.*;
หมวดความปลอดภัย enum {
หุ้น (Security.Stock.class), พันธบัตร (Security.Bond.class);
ค่าความปลอดภัย [];
SecurityCategory (ประเภท <? ขยายความปลอดภัย>) {
ค่า = kind.getEnumConstants();
-
ความปลอดภัยของอินเทอร์เฟซ {
enum Stock ดำเนินการรักษาความปลอดภัย { SHORT, LONG, MARGIN }
enum Bond ดำเนินการรักษาความปลอดภัย { เทศบาล, ขยะ }
-
การสุ่มเลือกความปลอดภัยสาธารณะ () {
กลับ Enums.random (ค่า);
-
โมฆะคงที่สาธารณะ main (String [] args) {
สำหรับ (int i = 0; i < 10; i ++) {
หมวดหมู่ SecurityCategory = Enums.random (SecurityCategory.class);
System.out.println (หมวดหมู่ + ": " +
Category.สุ่มเลือก());
-
-
} /* เอาต์พุต:
พันธบัตร: เทศบาล
พันธบัตร: เทศบาล
หุ้น: ขอบ
หุ้น: ขอบ
บอนด์: ขยะ
หุ้น: สั้น
สต็อก: ยาว
สต็อก: ยาว
พันธบัตร: เทศบาล
บอนด์: ขยะ
-
คัดลอกรหัสรหัส ดังต่อไปนี้:
//: แจกแจง/menu/Meal2.java
แพ็คเกจแจกแจงเมนู;
นำเข้า net.mindview.util.*;
มื้ออาหารสาธารณะ enum2 {
อาหารเรียกน้ำย่อย(Food.Appetizer.class),หลักสูตรหลัก(Food.MainCourse.class),ของหวาน(Food.Dessert.class),กาแฟ(Food.Coffee.class);
คุณค่าอาหารส่วนตัว[];
อาหารส่วนตัว2(ประเภท<? ขยายอาหาร>) {
ค่า = kind.getEnumConstants();
-
ส่วนต่อประสานสาธารณะ อาหาร {
enum Appetizer ใช้อาหาร {SALAD, SOUP, SPRING_ROLLS;}
enum MainCourse ประยุกต์อาหาร {LASAGNE, BURRITO, PAD_THAI,LENTILS, HUMMOUS, VINDALOO;}
enum ของหวานนำอาหาร {TIRAMISU, GELATO, BLACK_FOREST_CAKE,FRUIT, CREME_CARAMEL;}
enum Coffee ใช้อาหาร {BLACK_COFFEE, DECAF_COFFEE, ESPRESSO,LATTE, CAPPUCCINO, TEA, HERB_TEA;}
-
การสุ่มเลือกอาหารสาธารณะ () {
กลับ Enums.random (ค่า);
-
โมฆะคงที่สาธารณะ main (String [] args) {
สำหรับ (int i = 0; i < 5; i ++) {
สำหรับ(มื้อที่ 2 มื้อ : Meal2.values()) {
อาหาร อาหาร = มื้ออาหาร.สุ่มเลือก();
System.out.println(อาหาร);
-
System.out.println("---");
-
-
} /* เอาต์พุตเดียวกันกับ Meal.java *///:~
ใช้ EnumSet แทนการตั้งค่าสถานะ EnumSet ถูกเพิ่มใน Java SE5 เพื่อรวม enum และชุดเพื่อแทนที่การตั้งค่าสถานะบิตที่เป็นจำนวนเต็ม โดยปกติแล้วธงบิตใช้เพื่อระบุการสลับข้อมูลบางประเภท แต่ในโค้ด บิตจะดำเนินการมากกว่าแนวคิดที่มีความหมาย ดังนั้นจึงไม่ใช่เรื่องง่ายที่จะเข้าใจ EnumSet เร็วกว่าแฟล็กบิต โดยจะใช้แบบยาวภายในเพื่อแสดงเวกเตอร์บิต จากนั้นคุณสามารถใช้ภาษาเชิงแนวคิดเพิ่มเติมเพื่อแสดงการสลับบิตโดยไม่ต้องกังวลเรื่องประสิทธิภาพ องค์ประกอบใน EnumSet ต้องมาจากการแจงนับเดียวกัน ต่อไปนี้จะกำหนดการแจงนับของตำแหน่งสัญญาณเตือน:
คัดลอกรหัสรหัส ดังต่อไปนี้:
//: แจกแจง/AlarmPoints.java
แจกแจงแพ็คเกจ;
AlarmPoints สาธารณะ enum {STAIR1, STAIR2, LOBBY, OFFICE1, OFFICE2, OFFICE3, OFFICE4, BATHROOM, UTILITY, KITCHEN} ///:~
จากนั้นใช้คลาส EnumSet เพื่อติดตามสถานะของการเตือน:
คัดลอกรหัสรหัส ดังต่อไปนี้:
//: แจกแจง/EnumSets.java
// การดำเนินการบน EnumSets
แจกแจงแพ็คเกจ;
นำเข้า java.util.*;
นำเข้าแจกแจงคงที่ AlarmPoints. *;
นำเข้า net.mindview.util.Print.*;
EnumSets คลาสสาธารณะ {
โมฆะคงที่สาธารณะ main (String [] args) {
คะแนน EnumSet <AlarmPoints> = EnumSet.noneOf (AlarmPoints.class); // ชุดว่างเปล่า
point.add(ห้องน้ำ);
พิมพ์(คะแนน);
point.addAll(EnumSet.of(STAIR1, STAIR2, KITCHEN));
พิมพ์(คะแนน);
คะแนน = EnumSet.allOf (AlarmPoints.class);
point.removeAll(EnumSet.of(STAIR1, STAIR2, KITCHEN));
พิมพ์(คะแนน);
point.removeAll(EnumSet.range(OFFICE1, OFFICE4));
พิมพ์(คะแนน);
คะแนน = EnumSet.complementOf (คะแนน);
พิมพ์(คะแนน);
-
} /* เอาต์พุต:
[ห้องน้ำ]
[บันได 1 บันได 2 ห้องน้ำ ห้องครัว]
[ล็อบบี้, สำนักงาน1, สำนักงาน2, สำนักงาน3, สำนักงาน4, ห้องน้ำ, สาธารณูปโภค]
[ล็อบบี้ ห้องน้ำ สาธารณูปโภค]
[บันได1, บันได2, สำนักงาน1, สำนักงาน2, สำนักงาน3, สำนักงาน4, ห้องครัว]
-
EnumSet สร้างขึ้นจากประเภทยาวและมี 64 บิต แล้วถ้าประเภทการแจงนับของเราเกินจำนวนนี้ล่ะ
คัดลอกรหัสรหัส ดังต่อไปนี้:
//: แจงนับ/BigEnumSet.java
นำเข้า java.util.*;
BigEnumSet คลาสสาธารณะ {
enum ใหญ่ { A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10,A11, A12, A13, A14, A15, A16, A17, A18, A19, A20, A21,A22, A23 , A24, A25, A26, A27, A28, A29, A30, A31, A32,
A33, A34, A35, A36, A37, A38, A39, A40, A41, A42, A43,A44, A45, A46, A47, A48, A49, A50, A51, A52, A53, A54,A55, A56, A57, A58, A59, A60, A61, A62, A63, A64, A65,
A66, A67, A68, A69, A70, A71, A72, A73, A74, A75}
โมฆะคงที่สาธารณะ main (String [] args) {
EnumSet<ใหญ่> bigEnumSet = EnumSet.allOf(Big.class);
System.out.println(bigEnumSet);
-
} /* เอาต์พุต:
[A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19, A20, A21, A22, A23, A24 , A25, A26, A27, A28, A29, A30, A31, A32, A33, A34, A35, A36, A37, A38, A39, A40, A41, A42, A43, A44, A45, A46, A47, A48, A49, A50, A51, A52, A53, A54, A55, A56, A57, A58, A59, A60, A61, A62, A63, A64, A65, A66, A67, A68, A69, A70, A71, A72, A73, A74, A75]
-
เราจะเห็นว่าโปรแกรมกำลังทำงานตามปกติ ดังนั้นจึงมีความเป็นไปได้มากที่จะมีการเพิ่มประเภทยาวภายในเพื่อช่วยรองรับประเภทการแจงนับโดยใช้ EnumMap
EnumMap เป็นแผนที่ประเภทพิเศษ ค่าของคีย์สามารถเป็นประเภทในการแจงนับเดียวกันได้ ด้วยเหตุนี้ EnumMap จึงสามารถนำมาใช้ภายในผ่านอาร์เรย์ได้ ซึ่งมีประสิทธิภาพมาก
คัดลอกรหัสรหัส ดังต่อไปนี้:
//: แจกแจง/EnumMaps.java
// พื้นฐานของ EnumMaps
แจกแจงแพ็คเกจ;
นำเข้า java.util.*;
นำเข้าแจกแจงคงที่ AlarmPoints. *;
นำเข้า net.mindview.util.Print.*;
คำสั่งอินเทอร์เฟซ { การกระทำเป็นโมฆะ (); }
EnumMaps คลาสสาธารณะ {
โมฆะคงที่สาธารณะ main (String [] args) {
EnumMap<AlarmPoints,Command> em = EnumMap ใหม่<AlarmPoints,Command>(AlarmPoints.class);
em.put (ครัว, คำสั่งใหม่ () {
การกระทำที่เป็นโมฆะสาธารณะ () { พิมพ์ ("ไฟในครัว!");
-
em.put (ห้องน้ำ, คำสั่งใหม่ () {
การกระทำที่เป็นโมฆะสาธารณะ () { พิมพ์ ("การแจ้งเตือนในห้องน้ำ!");
-
สำหรับ (Map.Entry<AlarmPoints,Command> e : em.entrySet()) {
printnb(e.getKey() + ": ");
e.getValue().การกระทำ();
-
ลอง { // หากไม่มีค่าสำหรับคีย์ใดคีย์หนึ่ง:
em.get(ยูทิลิตี้).การกระทำ();
} จับ (ข้อยกเว้นจ) {
พิมพ์(จ);
-
-
} /* เอาต์พุต:
ห้องน้ำ: ห้องน้ำแจ้งเตือน!
ห้องครัว: ไฟไหม้ครัว!
java.lang.NullPointerException
-
วิธีการคงที่เฉพาะ การแจงนับ Java มีคุณลักษณะที่น่าสนใจมาก กล่าวคือ สามารถกำหนดลักษณะการทำงานที่แตกต่างกันสำหรับแต่ละอินสแตนซ์การแจงนับได้ เพื่อให้บรรลุเป้าหมายนี้ เราจึงกำหนดวิธีการเชิงนามธรรมอย่างน้อยหนึ่งวิธีให้เป็นส่วนหนึ่งของการแจงนับ จากนั้นจึงกำหนดลักษณะการทำงานที่แตกต่างกันสำหรับแต่ละวิธี อินสแตนซ์การแจงนับ วิธีการนิยามอินสแตนซ์การแจงนับ:
คัดลอกรหัสรหัส ดังต่อไปนี้:
//: แจกแจง/ConstantSpecificMethod.java
นำเข้า java.util.*;
นำเข้า java.text.*;
สาธารณะ enum ConstantSpecificMethod {
DATE_TIME {สตริง getInfo() {return DateFormat.getDateInstance().format(วันที่ใหม่());}},
CLASSPATH {สตริง getInfo() {return System.getenv("CLASSPATH");}},
เวอร์ชัน {สตริง getInfo() {return System.getProperty("java.version");}};
สตริงนามธรรม getInfo();
โมฆะคงที่สาธารณะ main (String [] args) {
สำหรับ (ConstantSpecificMethod csm : ค่า ())
System.out.println(csm.getInfo());
-
} /* (ดำเนินการเพื่อดูผลลัพธ์) *///:~
ดูเหมือนว่าโค้ดด้านบนจะติดอยู่ที่องค์ประกอบการแจงนับแต่ละรายการเป็นองค์ประกอบที่แตกต่างกัน และองค์ประกอบทั้งหมดสืบทอดมาจากคลาสฐาน ConstantSpecificMethod แต่เราไม่สามารถเข้าใจได้ด้วยวิธีนี้จริงๆ เนื่องจากเราไม่สามารถถือว่าองค์ประกอบการแจงนับเป็นประเภทได้:
คัดลอกรหัสรหัส ดังต่อไปนี้:
//: แจกแจง/NotClasses.java
// {Exec: javap -c LikeClasses}
นำเข้า net.mindview.util.Print.*;
enum LikeClasses {WINKEN { พฤติกรรมเป็นโมฆะ () { พิมพ์ ("พฤติกรรม 1" } }, BLINKEN { พฤติกรรมเป็นโมฆะ () { พิมพ์ ("พฤติกรรม 2"); NOD { พฤติกรรมเป็นโมฆะ () { พิมพ์ ("พฤติกรรม 3") ; } };
พฤติกรรมโมฆะนามธรรม ();
-
NotClasses คลาสสาธารณะ {
// เป็นโมฆะ f1 (อินสแตนซ์ LikeClasses.WINKEN) {} // ไม่
} /* เอาต์พุต:
เรียบเรียงจาก "NotClasses.java"
คลาสนามธรรม LikeClasses ขยาย java.lang.Enum {
LikeClasses สุดท้ายแบบคงที่สาธารณะ WINKEN;
LikeClasses BLINKEN สุดท้ายแบบคงที่สาธารณะ;
LikeClasses NOD สุดท้ายแบบคงที่สาธารณะ;
-
-
พิจารณาอีกตัวอย่างหนึ่ง มีเมนูล้างรถ ลูกค้าเลือกบริการที่แตกต่างกันตามเมนูที่แตกต่างกัน คุณสามารถใช้วิธีคงที่เฉพาะเพื่อเชื่อมโยงเมนูกับบริการ และใช้ EnumSet เพื่อรักษาตัวเลือกของลูกค้าได้ดังต่อไปนี้:
คัดลอกรหัสรหัส ดังต่อไปนี้:
//: แจกแจง/CarWash.java
นำเข้า java.util.*;
นำเข้า net.mindview.util.Print.*;
CarWash คลาสสาธารณะ {
วงจร enum สาธารณะ {UNDERBODY {การกระทำที่เป็นโมฆะ () { พิมพ์ ("การฉีดพ่นส่วนล่าง" }}
WHEELWASH {การกระทำที่เป็นโมฆะ () { พิมพ์ ("การล้างล้อ" }}
PREWASH {การกระทำที่เป็นโมฆะ () { พิมพ์ ("คลายสิ่งสกปรก" }}
พื้นฐาน {การกระทำที่เป็นโมฆะ () { พิมพ์ ("การล้างขั้นพื้นฐาน"); }}
HOTWAX {การกระทำที่เป็นโมฆะ () { พิมพ์ ("การใช้แว็กซ์ร้อน" }}
RINSE {การกระทำที่เป็นโมฆะ () { พิมพ์ ("การล้าง");
BLOWDRY {การกระทำที่เป็นโมฆะ () { พิมพ์ ("เป่าแห้ง" }};
การกระทำที่เป็นโมฆะนามธรรม ();
-
EnumSet<รอบ> รอบ = EnumSet.of(Cycle.BASIC, Cycle.RINSE);
เพิ่มโมฆะสาธารณะ (รอบวงจร) { รอบเพิ่ม (รอบ);
washCar เป็นโมฆะสาธารณะ () {
สำหรับ(รอบ c : รอบ)
ค.การกระทำ();
-
สตริงสาธารณะ toString () { กลับรอบ toString ();
โมฆะคงที่สาธารณะ main (String [] args) {
CarWash ล้าง = CarWash ใหม่ ();
พิมพ์(ล้าง);
wash.washCar();
// ลำดับการเพิ่มไม่สำคัญ:
wash.add(วงจร BLOWDRY);
wash.add(Cycle.BLOWDRY); // ละเว้นรายการที่ซ้ำกัน
wash.add(วงจร.RINSE);
wash.add(รอบ.HOTWAX);
พิมพ์(ล้าง);
wash.washCar();
-
} /* เอาต์พุต:
[พื้นฐาน, ล้าง]
การซักขั้นพื้นฐาน
กำลังล้าง
[ขั้นพื้นฐาน, ขี้ผึ้งร้อน, ล้าง, เป่าแห้ง]
การซักขั้นพื้นฐาน
การลงแวกซ์ร้อน
กำลังล้าง
เป่าแห้ง
-
นอกจากนี้เรายังสามารถแทนที่วิธีการคงที่เริ่มต้นเฉพาะแทนการใช้วิธีนามธรรมที่สืบทอดมาได้ดังต่อไปนี้:
คัดลอกรหัสรหัส ดังต่อไปนี้:
//: แจกแจง/OverrideConstantSpecific.java
นำเข้า net.mindview.util.Print.*;
สาธารณะ enum OverrideConstantSpecific {
NUT, BOLT, WASHER {เป็นโมฆะ f () { พิมพ์ ("วิธีการแทนที่" }};
เป็นโมฆะ f() { พิมพ์ ("พฤติกรรมเริ่มต้น");
โมฆะคงที่สาธารณะ main (String [] args) {
สำหรับ (OverrideConstantSpecific ocs : ค่า ()) {
printnb(ocs + `: ");
ocs.f();
-
-
} /* เอาต์พุต:
NUT: พฤติกรรมเริ่มต้น
BOLT: พฤติกรรมเริ่มต้น
WASHER: วิธีการแทนที่
-
บางครั้งเราต้องการส่งคำขอเฉพาะในห่วงโซ่ การรู้ว่าวัตถุในห่วงโซ่สามารถจัดการคำขอได้นั้นสามารถทำได้ง่าย ๆ โดยใช้วิธีคงที่เฉพาะต่อไปนี้คือตัวอย่างของการประมวลผลอีเมล:
คัดลอกรหัสรหัส ดังต่อไปนี้:
//: แจกแจง/PostOffice.java
//จำลองที่ทำการไปรษณีย์.
ประเภทแจกแจง 743
นำเข้า java.util.*;
นำเข้า net.mindview.util.*;
นำเข้า net.mindview.util.Print.*;
จดหมายชั้น {
// NO มีความเป็นไปได้ต่ำกว่าในการเลือกแบบสุ่ม:
enum การจัดส่งทั่วไป {ใช่, NO1, NO2, NO3, NO4, NO5}
ความสามารถในการสแกนแจกแจง {ไม่สามารถสแกนได้, ใช่1, ใช่2, ใช่3, ใช่4}
ความสามารถในการอ่านแจงนับ {ILLEGIBLE, YES1, YES2, YES3, YES4}
ที่อยู่ enum {ไม่ถูกต้อง, OK1, OK2, OK3, OK4, OK5, OK6}
enum ที่อยู่ส่งคืน {หายไป, ตกลง1, ตกลง2, ตกลง3, ตกลง4, ตกลง5}
การจัดส่งทั่วไปการจัดส่งทั่วไป;
ความสามารถในการสแกน ความสามารถในการสแกน;
ความสามารถในการอ่าน;
ที่อยู่;
ที่อยู่กลับ ที่อยู่กลับ;
ตัวนับแบบยาวคงที่ = 0;
รหัสยาว = ตัวนับ ++;
สตริงสาธารณะ toString() { กลับ "Mail" + id;
รายละเอียดสตริงสาธารณะ () {
return toString() + ", การจัดส่งทั่วไป: " + GeneralDelivery + ", ความสามารถในการสแกนที่อยู่: " + ความสามารถในการสแกน + ", ความสามารถในการอ่านที่อยู่: " + ความสามารถในการอ่าน +
", ที่อยู่ที่อยู่: " + ที่อยู่ + ", ที่อยู่ผู้ส่ง: " + ที่อยู่กลับ;
-
// สร้างเมลทดสอบ:
อีเมลสาธารณะแบบคงที่ RandomMail() {
เมล m = เมลใหม่ ();
m.generalDelivery= Enums.random(GeneralDelivery.class);
m.scannability = Enums.random (Scannability.class);
m.readability = Enums.random (ความสามารถในการอ่านคลาส);
m.address = Enums.random (ที่อยู่.คลาส);
m.returnAddress = Enums.random (ReturnAddress.class);
กลับม;
-
ตัวสร้าง Iterable <Mail> แบบคงที่สาธารณะ (จำนวน int สุดท้าย) {
ส่งคืน Iterable ใหม่ <Mail>() {
int n = นับ;
ตัววนซ้ำสาธารณะ <Mail> ตัววนซ้ำ () {
ส่งคืน Iterator ใหม่ <Mail>() {
บูลีนสาธารณะ hasNext () { ส่งคืน n--> 0;
จดหมายสาธารณะถัดไป () { กลับ RandomMail ();
โมฆะสาธารณะลบ () { // ไม่ได้ใช้งาน
โยน UnsupportedOperationException ใหม่ ();
-
-
-
-
-
-
ที่ทำการไปรษณีย์ชั้นเรียนสาธารณะ {
ระบุ MailHandler {
ทั่วไป_การจัดส่ง {
หมายเลขอ้างอิงบูลีน (Mail m) {
สวิตช์ (m.generalDelivery) {
กรณีที่ใช่:
print("ใช้การส่งแบบทั่วไปสำหรับ " + m);
กลับเป็นจริง;
ค่าเริ่มต้น: กลับเท็จ;
-
-
-
เครื่อง_สแกน {
หมายเลขอ้างอิงบูลีน (Mail m) {
สวิตช์ (m.scannability) {
กรณีที่ไม่สามารถสแกนได้: คืนค่าเท็จ;
ค่าเริ่มต้น:
สวิตช์ (m.address) {
กรณีไม่ถูกต้อง: คืนค่าเท็จ;
ค่าเริ่มต้น:
print("กำลังส่ง "+ m + " โดยอัตโนมัติ");
กลับเป็นจริง;
-
-
-
-
VISUAL_การตรวจสอบ {
หมายเลขอ้างอิงบูลีน (Mail m) {
สวิตช์ (m.readability) {
กรณีที่ไม่ถูกต้อง: ส่งกลับเท็จ;
ค่าเริ่มต้น:
สวิตช์ (m.address) {
กรณีไม่ถูกต้อง: คืนค่าเท็จ;
ค่าเริ่มต้น:
print("กำลังส่ง " + m + " ตามปกติ");
กลับเป็นจริง;
-
-
-
-
RETURN_TO_SENDER {
หมายเลขอ้างอิงบูลีน (Mail m) {
สวิตช์ (m.returnAddress) {
กรณีที่หายไป: คืนค่าเท็จ;
ค่าเริ่มต้น:
print("ส่งคืน " + m + " ถึงผู้ส่ง");
กลับเป็นจริง;
-
-
-
ตัวจัดการบูลีนนามธรรม (Mail m);
-
หมายเลขอ้างอิงโมฆะคงที่ (Mail m) {
สำหรับ (ตัวจัดการ MailHandler : MailHandler.values())
ถ้า (handler.handle (ม.))
กลับ;
print(m + " เป็นจดหมายที่ตายแล้ว");
-
โมฆะคงที่สาธารณะ main (String [] args) {
สำหรับ (เมลเมล : Mail.generator(10)) {
พิมพ์(mail.details());
จัดการ (จดหมาย);
พิมพ์("*****");
-
-
} /* เอาต์พุต:
Mail 0, การจัดส่งทั่วไป: NO2, การสแกนที่อยู่: ไม่สามารถสแกนได้, การอ่านที่อยู่: YES3, ที่อยู่ที่อยู่: OK1, ที่อยู่ผู้ส่ง: OK1
ส่ง Mail 0 ได้ตามปกติ
-
จดหมาย 1 การจัดส่งทั่วไป: NO5 ความสามารถในการสแกนที่อยู่: YES3 ความสามารถในการอ่านที่อยู่: ILLEGIBLE ที่อยู่ที่อยู่: OK5 ที่อยู่ผู้ส่ง: OK1
ส่ง Mail 1 อัตโนมัติ
-
จดหมาย 2 การจัดส่งทั่วไป: ใช่ การสแกนที่อยู่: YES3 ความสามารถในการอ่านที่อยู่: YES1 ที่อยู่ที่อยู่: OK1 ที่อยู่ผู้ส่ง: OK5
ใช้การจัดส่งทั่วไปสำหรับ Mail 2
-
จดหมาย 3 การจัดส่งทั่วไป: NO4 ความสามารถในการสแกนที่อยู่: YES3 ความสามารถในการอ่านที่อยู่: YES1 ที่อยู่ที่อยู่: ไม่ถูกต้อง ที่อยู่ผู้ส่ง: OK4
การส่งคืน Mail 3 ไปยังผู้ส่ง
-
Mail 4, การจัดส่งทั่วไป: NO4, การสแกนที่อยู่: ไม่สามารถสแกนได้, การอ่านที่อยู่: YES1, ที่อยู่ที่อยู่: ไม่ถูกต้อง, ที่อยู่ผู้ส่ง: OK2
การส่งคืน Mail 4 ไปยังผู้ส่ง
-
จดหมาย 5 การจัดส่งทั่วไป: NO3 ความสามารถในการสแกนที่อยู่: YES1 ความสามารถในการอ่านที่อยู่: ILLEGIBLE ที่อยู่ที่อยู่: OK4 ที่อยู่ผู้ส่ง: OK2
ส่ง Mail 5 อัตโนมัติ
-
จดหมาย 6 การจัดส่งทั่วไป: ใช่ การสแกนที่อยู่: YES4 ความสามารถในการอ่านที่อยู่: ILLEGIBLE ที่อยู่ที่อยู่: OK4 ที่อยู่ผู้ส่ง: OK4
ใช้การจัดส่งทั่วไปสำหรับ Mail 6
-
จดหมาย 7 การจัดส่งทั่วไป: ใช่ การสแกนที่อยู่: YES3 ความสามารถในการอ่านที่อยู่: YES4 ที่อยู่ที่อยู่: OK2 ที่อยู่ผู้ส่ง: MISSING
ใช้การจัดส่งทั่วไปสำหรับ Mail 7
-
จดหมาย 8 การจัดส่งทั่วไป: NO3 ความสามารถในการสแกนที่อยู่: YES1 ความสามารถในการอ่านที่อยู่: YES3 ที่อยู่ที่อยู่: ไม่ถูกต้อง ที่อยู่ผู้ส่ง: MISSING
จดหมาย 8 เป็นจดหมายถึงตาย
-
จดหมาย 9 การจัดส่งทั่วไป: NO1 การสแกนที่อยู่: ไม่สามารถสแกนได้ การอ่านที่อยู่: YES2 ที่อยู่ที่อยู่: OK1 ที่อยู่ผู้ส่ง: OK4
ส่งเมล์9ได้ตามปกติ
-
-
ประเภทการแจงนับยังเป็นประเภทที่เหมาะสำหรับการสร้างเครื่องสถานะอีกด้วย เครื่องสถานะสามารถย้ายระหว่างสถานะจำนวนจำกัดตามอินพุต จากนั้นจึงสิ้นสุดงานหลังจากถึงสถานะที่กำหนด นอกจากนี้ แต่ละสถานะจะมี เอาต์พุตที่สอดคล้องกัน เครื่องจำหน่ายสินค้าอัตโนมัติเป็นตัวอย่างของเครื่องสถานะทั่วไปที่เรากำหนดอินพุตที่แตกต่างกันภายในการแจงนับ:
คัดลอกรหัสรหัส ดังต่อไปนี้:
//: แจกแจง/Input.java
แจกแจงแพ็คเกจ;
นำเข้า java.util.*;
อินพุต enum สาธารณะ {
นิกเกิล(5), DIME(10), ไตรมาส(25), ดอลลาร์(100),ยาสีฟัน(200), ชิป(75), โซดา(100), สบู่(50),ABORT_TRANSACTION {
จำนวน int สาธารณะ () { // ไม่อนุญาต
โยน RuntimeException ใหม่ ("ABORT.amount()");
-
-
STOP { // นี่ต้องเป็นกรณีสุดท้าย
จำนวน int สาธารณะ () { // ไม่อนุญาต
โยน RuntimeException ใหม่ ("SHUT_DOWN.amount()");
-
-
ค่า int; // เป็นเซนต์
อินพุต (ค่า int) { this.value = value;
ป้อนข้อมูล() {}
int amount() { ค่าส่งคืน; };
แรนด์สุ่มแบบคงที่ = สุ่มใหม่ (47);
สาธารณะสุ่มเลือกอินพุตคงที่ () {
// ไม่รวม STOP:
ส่งกลับค่า()[rand.nextInt(ค่า().ความยาว - 1)];
-
-
VendingMachine ใช้เพื่อตอบสนองต่ออินพุต อันดับแรก จะจัดประเภทอินพุตผ่านการแจงนับหมวดหมู่ จากนั้นใช้คำสั่ง switch:
คัดลอกรหัสรหัส ดังต่อไปนี้:
//: แจกแจง/VendingMachine.java
// {Args: VendingMachineInput.txt}
แจกแจงแพ็คเกจ;
นำเข้า java.util.*;
นำเข้า net.mindview.util.*;
นำเข้าการแจกแจงคงที่อินพุต *;
นำเข้า net.mindview.util.Print.*;
แจกแจงหมวดหมู่ {
เงิน(NICKEL, DIME, QUARTER, DOLLAR),ITEM_SELECTION(ยาสีฟัน, ชิป, โซดา, สบู่),QUIT_TRANSACTION(ABORT_TRANSACTION),SHUT_DOWN(STOP);
ค่าอินพุตส่วนตัว [];
หมวดหมู่(ประเภทอินพุต) { ค่า = ประเภท }
ส่วนตัว EnumMap <Input,Category> หมวดหมู่ = EnumMap ใหม่ <Input,Category>(Input.class);
คงที่ {
สำหรับ(หมวดหมู่ c : Category.class.getEnumConstants())
สำหรับ (ประเภทอินพุต: c.values)
Category.put(ประเภท, c);
-
การจัดหมวดหมู่หมวดหมู่คงที่สาธารณะ (อินพุตอินพุต) {
กลับหมวดหมู่.get (อินพุต);
-
-
เครื่องจำหน่ายสินค้าอัตโนมัติระดับสาธารณะ {
สถานะรัฐคงที่ส่วนตัว = State.RESTING;
จำนวน int ส่วนตัวคงที่ = 0;
การเลือกอินพุตคงที่ส่วนตัว = null;
enum StateDuration {TRANSIENT} //การแท็ก enum
รัฐแจกแจง {
พักผ่อน {
เป็นโมฆะถัดไป (อินพุตอินพุต) {
สวิตช์ (Category.categorize (อินพุต)) {
กรณีเงิน:
จำนวน += input.amount();
รัฐ = เพิ่ม_เงิน;
หยุดพัก;
กรณี SHUT_DOWN:
รัฐ = เทอร์มินัล;
ค่าเริ่มต้น:
-
-
-
เพิ่ม_MONEY {
เป็นโมฆะถัดไป (อินพุตอินพุต) {
สวิตช์ (Category.categorize (อินพุต)) {
กรณีเงิน:
จำนวน += input.amount();
หยุดพัก;
กรณี ITEM_SELECTION:
การเลือก = อินพุต;
ถ้า (จำนวน < Selection.amount())
print("เงินไม่เพียงพอสำหรับการเลือก " +);
สถานะอื่น = การจ่าย;
หยุดพัก;
กรณี QUIT_TRANSACTION:
สถานะ = GIVING_CHANGE;
หยุดพัก;
กรณี SHUT_DOWN:
รัฐ = เทอร์มินัล;
ค่าเริ่มต้น:
-
-
-
การจ่ายยา (StateDuration.TRANSIENT) {
เป็นโมฆะถัดไป () {
print("นี่คือตัวเลือก " + ของคุณ);
จำนวน -= การเลือกจำนวน ();
สถานะ = GIVING_CHANGE;
-
-
GIVING_CHANGE(StateDuration.TRANSIENT) {
เป็นโมฆะถัดไป () {
ถ้า(จำนวน > 0) {
print("การเปลี่ยนแปลงของคุณ: " + จำนวน);
จำนวน = 0;
-
สถานะ = พักผ่อน;
-
-
TERMINAL { เอาท์พุทเป็นโมฆะ () { พิมพ์ ("หยุด" } };
บูลีนส่วนตัว isTransient = false;
สถานะ() {}
สถานะ (StateDuration trans) { isTransient = true;
เป็นโมฆะถัดไป (อินพุตอินพุต) {
โยน RuntimeException ใหม่ ("โทรเท่านั้น" + "ถัดไป (อินพุตอินพุต) สำหรับสถานะที่ไม่ชั่วคราว");
-
เป็นโมฆะถัดไป () {
โยน RuntimeException ใหม่ ("โทรเท่านั้นถัดไป () สำหรับ" + "สถานะ StateDuration.TRANSIENT");
-
เอาท์พุทเป็นโมฆะ () { พิมพ์ (จำนวน);
-
การรันโมฆะแบบคงที่ (เครื่องกำเนิด <Input> gen) {
ในขณะที่ (สถานะ != รัฐ TERMINAL) {
state.next(gen.ถัดไป());
ในขณะที่ (state.isTransient)
state.ถัดไป();
รัฐ.เอาท์พุท();
-
-
โมฆะคงที่สาธารณะ main (String [] args) {
Generator<Input> gen = new RandomInputGenerator();
ถ้า (args.length == 1)
Gen = FileInputGenerator ใหม่ (args [0]);
วิ่ง (เจน);
-
-
// สำหรับการตรวจสอบสุขภาพขั้นพื้นฐาน:
คลาส RandomInputGenerator ใช้ Generator<Input> {
อินพุตสาธารณะถัดไป () { return Input.randomSelection ();
-
// สร้างอินพุตจากไฟล์ ';'-สตริงที่แยกจากกัน:
คลาส FileInputGenerator ใช้ Generator<Input> {
อินพุต Iterator ส่วนตัว <String>;
FileInputGenerator สาธารณะ (ชื่อไฟล์สตริง) {
input = new TextFile(fileName, ";").iterator();
-
อินพุตสาธารณะถัดไป () {
ถ้า(!input.hasNext())
กลับเป็นโมฆะ;
กลับ Enum.valueOf(Input.class, input.next().trim());
-
} /* เอาต์พุต:
นี่คือชิปของคุณ
นี่คือยาสีฟันของคุณ
การเปลี่ยนแปลงของคุณ: 35
เงินไม่เพียงพอสำหรับ SODA
เงินไม่เพียงพอสำหรับ SODA
การเปลี่ยนแปลงของคุณ: 75
หยุดแล้ว
-
นี่คือข้อมูลทดสอบที่ใช้ในการสร้างผลลัพธ์ข้างต้น:
คัดลอกรหัสรหัส ดังต่อไปนี้:
ไตรมาส; ไตรมาส;
ดอลลาร์; ดอลลาร์;
ไตรมาส; DIME; ABORT_TRANSACTION;
ไตรมาส; DIME;
ไตรมาส; DIME;
ยกเลิกธุรกรรม;
หยุด;
-
Multiple unpacking เมื่อต้องรับมือกับการโต้ตอบระหว่างหลายประเภท โค้ดมีแนวโน้มที่จะยุ่งเหยิง เช่น Number.plush(Number), Number.mutiply(Number) เป็นต้น Number เป็นเพียงคลาสพื้นฐานของตระกูล ดังนั้นเมื่อคุณเรียกใช้ เมื่อ a.plus(b) คุณไม่รู้ประเภทของ a และประเภทของ b ดังนั้นจะแน่ใจได้อย่างไรว่าปฏิสัมพันธ์ระหว่างสิ่งเหล่านั้นถูกต้อง Java ดำเนินการคลายแพ็กได้เพียงครั้งเดียว นั่นคือ หากมีการดำเนินการหนึ่งรายการขึ้นไปจากประเภทที่ไม่รู้จักหลายประเภท Java จะดำเนินการกลไกการเชื่อมโยงแบบไดนามิกกับประเภทใดประเภทหนึ่งเท่านั้น ซึ่งไม่สามารถแก้ปัญหาที่เราพูดถึงข้างต้นได้ ดังนั้นคุณจึงมี เพื่อเขียนโค้ดการเชื่อมโยงแบบไดนามิกด้วยตนเอง
วิธีแก้ไขคือการใช้มัลติไบน์ดิ้ง ความหลากหลายสามารถเกิดขึ้นได้เฉพาะเมื่อเรียกใช้เมธอดเท่านั้น ดังนั้น หากคุณต้องการแตกแพ็กหลายครั้ง คุณต้องเรียกใช้เมธอดหลายวิธี ด้วยการแกะหลายรายการ คุณต้องมีเมธอดเสมือนที่เรียกเมธอดของแต่ละประเภทเพื่อแกะ ตัวอย่างต่อไปนี้เป็นตัวอย่างเป่ายิ้งฉุบ:
คัดลอกรหัสรหัส ดังต่อไปนี้:
//: แจงนับ/Outcome.java
แจกแจงแพ็คเกจ;
ผลลัพธ์สาธารณะ { ชนะ แพ้ เสมอ } ///:~
//: แจกแจง/RoShamBo1.java
// การสาธิตการส่งแบบหลายรายการ
แจกแจงแพ็คเกจ;
นำเข้า java.util.*;
นำเข้าแจกแจงคงที่ผลลัพธ์ *;
รายการอินเทอร์เฟซ {
การแข่งขันผลลัพธ์ (รายการมัน);
การประเมินผลลัพธ์ (กระดาษ p);
การประเมินผลลัพธ์(กรรไกร);
การประเมินผลลัพธ์ (Rock r);
-
กระดาษคลาสดำเนินการรายการ {
แข่งขันผลลัพธ์สาธารณะ (รายการ) { return it.eval (สิ่งนี้);
การประเมินผลลัพธ์สาธารณะ (กระดาษ p) { return DRAW;
การประเมินผลลัพธ์สาธารณะ (กรรไกร) { ชนะกลับ;
การประเมินผลลัพธ์สาธารณะ (Rock r) { กลับสูญเสีย;
สตริงสาธารณะ toString() { กลับ "กระดาษ";
-
คลาสกรรไกรใช้รายการ {
แข่งขันผลลัพธ์สาธารณะ (รายการ) { return it.eval (สิ่งนี้);
การประเมินผลลัพธ์สาธารณะ (กระดาษ p) { กลับสูญเสีย;
การประเมินผลลัพธ์สาธารณะ (กรรไกร) { return DRAW;
การประเมินผลลัพธ์สาธารณะ (Rock r) { ชนะกลับ;
สตริงสาธารณะ toString () { กลับ "กรรไกร";
-
คลาสร็อคใช้รายการ {
แข่งขันผลลัพธ์สาธารณะ (รายการ) { return it.eval (สิ่งนี้);
การประเมินผลลัพธ์สาธารณะ (กระดาษ p) { ชนะกลับ;
ผลการศึกษาสาธารณะ (กรรไกร s) {return lose;}
ผลการศึกษาสาธารณะ (Rock R) {Return Draw;
Public String ToString () {return "Rock";
-
ชั้นเรียนสาธารณะ Roshambo1 {
ขนาด int สุดท้ายคงที่ = 20;
Rand แบบสุ่มแบบคงที่ส่วนตัว = ใหม่สุ่ม (47);
รายการคงที่สาธารณะ newItem () {
สวิตช์ (rand.nextint (3)) {
ค่าเริ่มต้น:
กรณีที่ 0: ส่งคืนกรรไกรใหม่ ();
กรณีที่ 1: คืนกระดาษใหม่ ();
กรณีที่ 2: คืนใหม่ร็อค ();
-
-
การจับคู่โมฆะคงที่สาธารณะ (รายการ A, รายการ B) {
System.out.println (a + "vs. " + b + ":" + A.Compete (b));
-
โมฆะคงที่สาธารณะ main (String [] args) {
สำหรับ (int i = 0; i <size; i ++)
Match (newItem (), newItem ());
-
} /* เอาต์พุต:
ร็อคกับร็อค: วาด
กระดาษกับร็อค: ชนะ
กระดาษกับร็อค: ชนะ
กระดาษกับร็อค: ชนะ
กรรไกรกับกระดาษ: ชนะ
กรรไกรกับกรรไกร: วาด
กรรไกรกับกระดาษ: ชนะ
ร็อคกับกระดาษ: แพ้
กระดาษกับกระดาษ: วาด
ร็อคกับกระดาษ: แพ้
กระดาษกับกรรไกร: แพ้
กระดาษกับกรรไกร: แพ้
ร็อคกับกรรไกร: ชนะ
ร็อคกับกระดาษ: แพ้
กระดาษกับร็อค: ชนะ
กรรไกรกับกระดาษ: ชนะ
กระดาษกับกรรไกร: แพ้
กระดาษกับกรรไกร: แพ้
กระดาษกับกรรไกร: แพ้
กระดาษกับกรรไกร: แพ้
-
เราใช้วิธีการหลายอย่างเพื่อให้ได้การเปิดตัวหลายครั้ง แต่สิ่งที่เราได้รับคือโครงสร้างรหัสที่ดี ปัญหาที่ใหญ่ที่สุดเมื่อใช้โซลูชันการแจงนับเพื่อใช้รหัสข้างต้นคืออินสแตนซ์การแจงนับไม่ใช่ประเภทดังนั้นอินสแตนซ์การแจงนับไม่สามารถใช้เป็นประเภทพารามิเตอร์ แต่เรายังสามารถมีวิธีอื่น ๆ ในการหลีกเลี่ยงอุปสรรคนี้
คัดลอกรหัสรหัส ดังต่อไปนี้:
//: แจกแจง/roshambo2.java
// สลับหนึ่ง enum หนึ่งในอีก
แพ็คเกจแจกแจง;
นำเข้า enumerated Static.outcome.*;
Public Enum Roshambo2 ใช้คู่แข่ง <Roshambo2> {
กระดาษ (วาด, แพ้, ชนะ), กรรไกร (ชนะ, วาด, แพ้), ร็อค (แพ้, ชนะ, จับ);
ผลลัพธ์ส่วนตัว vpaper, vscissors, vrock;
Roshambo2 (กระดาษผลลัพธ์, กรรไกรผลลัพธ์, ผลลัพธ์หิน) {
this.vpaper = กระดาษ;
this.vscissors = กรรไกร;
this.vrock = rock;
-
การแข่งขันผลการแข่งขันสาธารณะ (Roshambo2 IT) {
สลับ (มัน) {
ค่าเริ่มต้น:
Case Paper: return vpaper;
กรรไกรกรณี: return vscissors;
Case Rock: Return Vrock;
-
-
โมฆะคงที่สาธารณะ main (String [] args) {
Roshambo.play (Roshambo2.class, 20);
-
} /* เอาต์พุต:
ร็อคกับร็อค: วาด
กรรไกรกับร็อค: แพ้
กรรไกรกับร็อค: แพ้
ประเภทที่แจกแจง 753
กรรไกรกับร็อค: แพ้
กระดาษกับกรรไกร: แพ้
กระดาษกับกระดาษ: วาด
กระดาษกับกรรไกร: แพ้
ร็อคกับกรรไกร: ชนะ
กรรไกรกับกรรไกร: วาด
ร็อคกับกรรไกร: ชนะ
กรรไกรกับกระดาษ: ชนะ
กรรไกรกับกระดาษ: ชนะ
ร็อคกับกระดาษ: แพ้
ร็อคกับกรรไกร: ชนะ
กรรไกรกับร็อค: แพ้
กระดาษกับกรรไกร: แพ้
กรรไกรกับกระดาษ: ชนะ
กรรไกรกับกระดาษ: ชนะ
กรรไกรกับกระดาษ: ชนะ
กรรไกรกับกระดาษ: ชนะ
-
คัดลอกรหัสรหัส ดังต่อไปนี้:
//: แจกแจง/คู่แข่ง. จาวา
// สลับหนึ่ง enum หนึ่งในอีก
แพ็คเกจแจกแจง;
คู่แข่งส่วนต่อประสานสาธารณะ <t ขยายคู่แข่ง <t>> {
การแข่งขันผลลัพธ์ (T คู่แข่ง);
-
คัดลอกรหัสรหัส ดังต่อไปนี้:
//: แจกแจง/roshambo.java
// เครื่องมือทั่วไปสำหรับตัวอย่าง Roshambo
แพ็คเกจแจกแจง;
นำเข้า net.mindview.util.*;
ชั้นเรียนสาธารณะ Roshambo {
สาธารณะคงที่ <t ขยายคู่แข่ง <T >> การจับคู่เป็นโมฆะ (t a, t b) {
System.out.println (a + "vs. " + b + ":" + A.Compete (b));
-
สาธารณะคงที่ <t ขยาย enum <t> & คู่แข่ง <t>> การเล่นเป็นโมฆะ (คลาส <t> rsbclass ขนาด int) {
สำหรับ (int i = 0; i <size; i ++)
การจับคู่ (enums.random (rsbclass), enums.random (rsbclass));
-
-
เนื่องจากการกำหนดวิธีการคงที่สามารถให้วิธีการที่แตกต่างกันสำหรับแต่ละประเภทการแจงนับดูเหมือนว่าจะเป็นทางออกที่ดีในการเปิดออกหลายครั้ง แต่เรายังคงเผชิญกับปัญหาที่อินสแตนซ์การแจงนับไม่ใช่ประเภทดังนั้นสิ่งที่เราทำได้คือเพิ่มคำสั่งสวิตช์ : :
คัดลอกรหัสรหัส ดังต่อไปนี้:
//: แจกแจง/roshambo3.java
// ใช้วิธีการเฉพาะคงที่
แพ็คเกจแจกแจง;
นำเข้า enumerated Static.outcome.*;
Public Enum Roshambo3 ใช้คู่แข่ง <Roshambo3> {
กระดาษ {
การแข่งขันผลการแข่งขันสาธารณะ (Roshambo3 IT) {
สลับ (มัน) {
ค่าเริ่มต้น: // เพื่อวางคอมไพเลอร์
Case Paper: การดึงกลับ;
เคสกรรไกร: Return Lose;
Case Rock: Return Win;
-
-
-
กรรไกร {
การแข่งขันผลการแข่งขันสาธารณะ (Roshambo3 IT) {
สลับ (มัน) {
ค่าเริ่มต้น:
Case Paper: Return Win;
กรรไกรกรณี: การดึงกลับ;
Case Rock: Return Lose;
-
-
-
หิน {
การแข่งขันผลการแข่งขันสาธารณะ (Roshambo3 IT) {
สลับ (มัน) {
ค่าเริ่มต้น:
Case Paper: Return Lose;
เคสกรรไกร: Return Win;
Case Rock: Return Draw;
-
-
-
การแข่งขันบทคัดย่อสาธารณะ (Roshambo3 IT);
โมฆะคงที่สาธารณะ main (String [] args) {
Roshambo.play (Roshambo3.class, 20);
-
}/ * เอาต์พุตเดียวกับ roshambo2.java * ///: ~
รหัสต่อไปนี้เป็นวิธีการใช้งานที่รัดกุมมากขึ้น:
คัดลอกรหัสรหัส ดังต่อไปนี้:
//: แจกแจง/roshambo4.java
แพ็คเกจแจกแจง;
Public Enum Roshambo4 ใช้คู่แข่ง <Roshambo4> {
หิน {
ผลการแข่งขันสาธารณะ (คู่ต่อสู้ Roshambo4) {
การแข่งขันกลับ (กรรไกร, คู่ต่อสู้);
-
-
กรรไกร {
ผลการแข่งขันสาธารณะ (คู่ต่อสู้ Roshambo4) {
กลับการแข่งขัน (กระดาษ, คู่ต่อสู้);
-
-
กระดาษ {
ผลการแข่งขันสาธารณะ (คู่ต่อสู้ Roshambo4) {
การแข่งขันกลับ (ร็อค, คู่ต่อสู้);
-
-
การแข่งขันผลลัพธ์ (Roshambo4 Loser, Roshambo4 ฝ่ายตรงข้าม) {
return ((ฝ่ายตรงข้าม == สิ่งนี้)? ผลลัพธ์. draw: ((ฝ่ายตรงข้าม == ผู้แพ้)? ผลลัพธ์. win: ผลลัพธ์. lose));
-
โมฆะคงที่สาธารณะ main (String [] args) {
Roshambo.play (Roshambo4.class, 20);
-
}/ * เอาต์พุตเดียวกับ roshambo2.java * ///: ~
คลาส enummap ดูเหมือนจะเป็นวิธีที่ดีในการใช้งานการเปิดตัวหลายครั้ง:
คัดลอกรหัสรหัส ดังต่อไปนี้:
//: แจกแจง/roshambo5.java
// การจัดส่งหลายครั้งโดยใช้ enummap ของ enummaps
แพ็คเกจแจกแจง;
นำเข้า java.util.*;
นำเข้า enumerated Static.outcome.*;
Enum Roshambo5 ใช้คู่แข่ง <Roshambo5> {
กระดาษกรรไกรหิน;
enummap แบบคงที่ <Roshambo5, enummap <Roshambo5, ผลลัพธ์ >> ตาราง = new Enummap <Roshambo5, enummap <Roshambo5, ผลลัพธ์ >> (Roshambo5.class);
คงที่ {
สำหรับ (Roshambo5 IT: Roshambo5.Values ())
table.put (it, enummap ใหม่ <roshambo5, ผลลัพธ์> (roshambo5.class));
initrow (กระดาษ, วาด, แพ้, ชนะ);
initrow (กรรไกร, ชนะ, วาด, แพ้);
initrow (ร็อค, แพ้, ชนะ, วาด);
-
ช่องว่างคงที่ initrow (roshambo5 it, ผลลัพธ์ vpaper, ผลลัพธ์ vscissors, ผลลัพธ์ vrock) {
enummap <roshambo5, ผลลัพธ์> row = roshambo5.table.get (มัน);
row.put (roshambo5.paper, vpaper);
row.put (Roshambo5.scissors, vscissors);
row.put (roshambo5.rock, vrock);
-
การแข่งขันผลการแข่งขันสาธารณะ (Roshambo5 IT) {
กลับ table.get (นี่) .get (it);
-
โมฆะคงที่สาธารณะ main (String [] args) {
Roshambo.play (Roshambo5.class, 20);
-
}/ * เอาต์พุตเดียวกับ roshambo2.java * ///: ~
นอกจากนี้เรายังสามารถใช้คุณสมบัติของอินสแตนซ์การแจงนับที่มีค่าคงที่เพื่อใช้ข้อมูลสำหรับวิธีการใช้งานที่ง่ายที่สุด
คัดลอกรหัสรหัส ดังต่อไปนี้:
//: แจกแจง/roshambo6.java
// enums โดยใช้ "ตาราง" แทนการจัดส่งหลายครั้ง
แพ็คเกจแจกแจง;
นำเข้า enumerated Static.outcome.*;
Enum Roshambo6 ใช้คู่แข่ง <Roshambo6> {
กระดาษกรรไกรหิน;
ผลลัพธ์คงที่ส่วนตัว [] [] table = {
{draw, lose, win}, // paper
{win, draw, lose}, // กรรไกร
{แพ้, ชนะ, วาด}, // rock
-
การแข่งขันผลการแข่งขันสาธารณะ (Roshambo6 อื่น ๆ ) {
ตารางกลับ [this.ordinal ()] [other.ordinal ()];
-
โมฆะคงที่สาธารณะ main (String [] args) {
Roshambo.play (Roshambo6.class, 20);
-
-