อะไรคือข้อดีของ Java enum กับคลาสที่มี public static final field?


147

ฉันคุ้นเคยกับ C # มาก แต่เริ่มทำงานได้มากขึ้นใน Java ฉันคาดหวังที่จะเรียนรู้ว่า enums ใน Java นั้นโดยทั่วไปเทียบเท่ากับใน C # แต่เห็นได้ชัดว่านี่ไม่ใช่กรณี ตอนแรกฉันรู้สึกตื่นเต้นที่ได้เรียนรู้ว่า Java enums อาจมีข้อมูลหลายชิ้นซึ่งดูเหมือนว่ามีประโยชน์มาก ( http://docs.oracle.com/javase/tutorial/java/javaOO/enum.html ) อย่างไรก็ตามตั้งแต่นั้นฉันได้พบคุณสมบัติมากมายที่ขาดหายไปเล็กน้อยใน C # เช่นความสามารถในการกำหนดองค์ประกอบ enum ได้อย่างง่ายดายด้วยค่าที่แน่นอนและดังนั้นความสามารถในการแปลงจำนวนเต็มเป็น enum โดยไม่ต้องใช้ความพยายามอย่างมาก ( ie แปลงค่าจำนวนเต็มเป็นการจับคู่ Enum Java )

ดังนั้นคำถามของฉันคือ: มีประโยชน์กับ Java enums มากกว่าชั้นเรียนที่มีทุ่งสุดท้ายคงที่สาธารณะ? หรือว่าเป็นเพียงแค่ให้มีขนาดกะทัดรัดมากขึ้นไวยากรณ์?

แก้ไข: ให้ฉันชัดเจนยิ่งขึ้น อะไรคือประโยชน์ของ Java enums มากกว่าชั้นเรียนที่มีกลุ่มของเขตข้อมูลสุดท้ายคงที่ประเภทเดียวกัน ? ตัวอย่างเช่นในตัวอย่างของดาวเคราะห์ที่ลิงก์แรกสิ่งที่เป็นข้อได้เปรียบของ enum ในชั้นเรียนที่มีค่าคงที่สาธารณะเหล่านี้:

public static final Planet MERCURY = new Planet(3.303e+23, 2.4397e6);
public static final Planet VENUS = new Planet(4.869e+24, 6.0518e6);
public static final Planet EARTH = new Planet(5.976e+24, 6.37814e6);
public static final Planet MARS = new Planet(6.421e+23, 3.3972e6);
public static final Planet JUPITER = new Planet(1.9e+27, 7.1492e7);
public static final Planet SATURN = new Planet(5.688e+26, 6.0268e7);
public static final Planet URANUS = new Planet(8.686e+25, 2.5559e7);
public static final Planet NEPTUNE = new Planet(1.024e+26, 2.4746e7);

เท่าที่ฉันจะบอกได้คำตอบของคาซาบลังก้าเป็นคำตอบเดียวที่ตอบสนองได้


4
@Bohemian: มันอาจจะไม่ซ้ำกันตั้งแต่ OP ดังกล่าวเพียงpublic static finalสาขาซึ่งอาจจะพิมพ์ค่าและไม่จำเป็นต้องints
casablanca

1
@Shahzeb แทบจะไม่ เห็นได้ชัดว่าใช้ enums แทนค่าคงที่สตริงเป็นความคิดที่ดีมากและได้รับการสนับสนุนมากกว่า ประเภทความปลอดภัยไม่ต้องการฟังก์ชั่นยูทิลิตี้คงที่และอื่น ๆ .. ไม่มีเหตุผลที่จะใช้สตริงแทน
Voo

1
@ Voo ใช่ฉันรู้ว่าจะมีความขัดแย้งและนี่คือหนึ่งใน 49 วินาที Enums นั้นยอดเยี่ยม (และฉันรักพวกเขาและใช้บ่อยมาก) แต่คุณต้องการความปลอดภัยประเภทใดเมื่อประกาศค่าคงที่หรือใช้มัน เป็น overkill เพื่อสร้าง enum ทุกครั้งที่คุณต้องการประกาศค่าคงที่สำหรับตัวอักษร String
Shahzeb

4
@Shahzeb หากคุณมีตัวแปรตัวเดียวให้แน่ใจว่าใช้สตริงไม่สามารถเกิดขึ้นได้มากที่นี่ (ค่าเดียวค่อนข้างไม่มีจุดหมายเป็นพารามิเตอร์) แต่ทราบว่าเรากำลังพูดถึงค่าคงที่Sดังนั้นตอนนี้เรากำลังพูดถึงอาจส่งผ่านพวกเขาไปยังฟังก์ชั่น ฯลฯ เราต้องการความปลอดภัยประเภทหรือไม่? ดีไม่มี แต่แล้วคนส่วนใหญ่พิจารณาประเภท c สไตล์ของ "ทุกอย่างเป็นvoid*สไตล์ที่ดี" และมันสามารถหยุดข้อบกพร่อง (โดยเฉพาะถ้าผ่านพารามิเตอร์ enum / string มากกว่าหนึ่งตัว) นอกจากนี้มันยังทำให้ค่าคงที่อยู่ในเนมสเปซของตัวเอง ฯลฯ ตรงกันข้ามกับที่ไม่มีประโยชน์จริง ๆ เพียงแค่มีตัวแปรธรรมดา
Voo

3
@ โบฮีเมียน: ฉันไม่เห็นวิธี ด้วยints ไม่มีความปลอดภัยประเภทเพราะใครสามารถผ่านค่าใด ๆ ในทางกลับกันวัตถุที่พิมพ์ออกมานั้นไม่ต่างจาก enums ในแง่ของความปลอดภัยของประเภท
casablanca

คำตอบ:


78

เทคนิคหนึ่งสามารถดู enums เป็นชั้นเรียนที่มีกลุ่มของค่าคงที่พิมพ์และนี่คือความจริงที่ว่าค่าคง enum จะดำเนินการภายใน ใช้enumแต่ช่วยให้คุณมีวิธีการที่เป็นประโยชน์ ( Enum Javadoc ) Enum.valueOfที่คุณมิฉะนั้นจะต้องดำเนินการด้วยตัวเองเช่น


14
นอกจากนี้ยังมี.values()การวนซ้ำในรายการค่า
h3xStream

1
นี่ดูเหมือนจะเป็นคำตอบที่ถูกต้องแม้ว่าจะไม่ได้รับความพึงพอใจมากก็ตาม ในความคิดของฉันมันค่อนข้างคุ้มค่าสำหรับ Java ที่จะเพิ่มการสนับสนุนสำหรับ enums สำหรับไวยากรณ์ที่มีขนาดกะทัดรัดมากขึ้นและการเข้าถึงวิธี Enum
Craig W

7
@ รวบรวมสัญชาตญาณของคุณถูกต้อง - นี่เป็นคำตอบที่แย่มากเพราะมันพลาดจุดประสงค์ทั้งหมดของ enums ดูความคิดเห็นของฉันภายใต้คำถามเพื่อเป็นส่วนหนึ่งของเหตุผลว่าทำไม
โบฮีเมียน

1
@ โบฮีเมียน: ฉันไม่ได้ "พลาดจุดประสงค์" ของ enums - ฉันใช้มันตลอดเวลา ดูการตอบสนองต่อความคิดเห็นของคุณด้านบน
casablanca

1
Enum.valuesOf วิธีการคืนวัตถุเดียวกันถ้าเรียกว่าสองครั้ง?
Emre Aktürk

104
  1. พิมพ์ความปลอดภัยและความปลอดภัยที่คุ้มค่า
  2. รับประกันซิงเกิล
  3. ความสามารถในการกำหนดและแทนที่วิธีการ
  4. ความสามารถในการใช้ค่าในswitchข้อความcaseสั่งโดยไม่มีคุณสมบัติ
  5. ลำดับของค่าในตัวผ่านทาง ordinal().
  6. การทำให้เป็นอนุกรมตามชื่อไม่ใช่ตามค่าซึ่งเสนอระดับการพิสูจน์อักษรในอนาคต
  7. EnumSetและEnumMapชั้นเรียน

19
ต้องบอกว่าทุกครั้งที่ฉันใส่รหัสลงใน Enum ฉันรู้สึกเสียใจ
มาร์ควิสแห่ง Lorne

4
ทำไมคุณถึงเสียใจ? ฉันไม่เคย ...
glglgl

2
@glglgl เพราะมันใส่โค้ดเฉพาะแอปพลิเคชันในสถานที่ที่ฉันรู้สึกว่ามันไม่ได้เป็นของจริงนั่นเป็นเพียงการกำหนดชุดของค่า ถ้าฉันต้องทำอีกฉันจะรวมไว้ในหนึ่งในหลายswitchงบที่เป็นแรงบันดาลใจดั้งเดิมสำหรับการใช้Enumเลย
มาร์ควิสแห่ง Lorne

72

ไม่มีใครพูดถึงความสามารถในการใช้พวกเขาในswitchงบ; ฉันจะโยนมันเข้าไปด้วย

สิ่งนี้อนุญาตให้ใช้ enums ที่ซับซ้อนโดยพลการในวิธีที่สะอาดโดยไม่ต้องใช้ลำดับที่instanceofอาจทำให้สับสนifหรือค่าการสลับที่ไม่ใช่สตริง / int ตัวอย่างที่บัญญัติเป็นเครื่องรัฐ


อย่างไรก็ตามคุณไม่ได้กล่าวถึงผลประโยชน์ใด ๆ จาก enums vs static field คุณสามารถใช้คำสั่ง switch กับสแตติกฟิลด์ที่มีชนิดเพียงพอ Op ต้องการฟังก์ชั่นจริงหรือความแตกต่างในการทำงาน
Genaut

@Genaut ประโยชน์คือ enums มีฟังก์ชั่นมากกว่าสตริงหรือคำถามที่เกี่ยวกับความแตกต่างซึ่งฉันให้ OP ทราบแล้วว่า enums คืออะไรและไม่มีใครพูดถึงคำสั่ง switch เมื่อฉันโพสต์เมื่อ 4.5 ปีที่แล้วและอย่างน้อยคนสองสามคนพบว่ามันให้ข้อมูลใหม่¯_ (ツ) _ / ¯
Dave Newton

44

ข้อได้เปรียบหลักคือความปลอดภัยประเภท ด้วยชุดของค่าคงที่คุณสามารถใช้ค่าใด ๆ ของชนิดที่อยู่ภายในเหมือนกันได้ซึ่งจะแนะนำข้อผิดพลาด ด้วย enum สามารถใช้ค่าที่ใช้ได้เท่านั้น

ตัวอย่างเช่น

public static final int SIZE_SMALL  = 1;
public static final int SIZE_MEDIUM = 2;
public static final int SIZE_LARGE  = 3;

public void setSize(int newSize) { ... }

obj.setSize(15); // Compiles but likely to fail later

VS

public enum Size { SMALL, MEDIUM, LARGE };

public void setSize(Size s) { ... }

obj.setSize( ? ); // Can't even express the above example with an enum

3
คลาสยังพิมพ์เซฟ ... : / (สมมติว่าฟิลด์สแตติกเป็นประเภทของคลาสคอนเทนเนอร์)
h3xStream

คุณยังคงสามารถส่งผ่านค่าที่ไม่ถูกต้องได้ แต่มันจะเป็นข้อผิดพลาดในการรวบรวมเวลาซึ่งง่ายต่อการตรวจจับ
zzzzzzzzzzzzzzzzzzzzzzzzzzzzzz

2
คุณสามารถโทรsetSize(null)ในตัวอย่างที่สองของคุณ แต่มีแนวโน้มที่จะล้มเหลวเร็วกว่าข้อผิดพลาดของตัวอย่างแรก
เจฟฟรีย์

42

มีความสับสนน้อยลง ใช้Fontตัวอย่างเช่น มันมีตัวสร้างที่ใช้ชื่อของที่Fontคุณต้องการขนาดและสไตล์ของมัน ( new Font(String, int, int)) ถึงวันนี้ฉันจำไม่ได้ว่าสไตล์หรือขนาดไปก่อน หากFontได้ใช้enumสำหรับทุกรูปแบบที่แตกต่างกัน ( PLAIN, BOLD, ITALIC, BOLD_ITALIC) คอนสตรัคของมันจะมีลักษณะFont(String, Style, int)การป้องกันความสับสนใด ๆ น่าเสียดายที่enumไม่ได้อยู่ใกล้ ๆ เมื่อสร้างFontชั้นเรียนและเนื่องจาก Java ต้องรักษาความเข้ากันได้แบบย้อนกลับเราจะถูกรบกวนด้วยความคลุมเครือนี้เสมอ

แน่นอนว่านี่เป็นเพียงอาร์กิวเมนต์สำหรับใช้enumแทนpublic static finalค่าคงที่ Enums ยังสมบูรณ์แบบสำหรับsingletonsและการใช้พฤติกรรมเริ่มต้นในขณะที่อนุญาตให้ปรับแต่งในภายหลัง (IE รูปแบบกลยุทธ์ ) ตัวอย่างของหลังเป็นjava.nio.file's OpenOptionและStandardOpenOptionถ้านักพัฒนาต้องการที่จะสร้างไม่ได้มาตรฐานของเขาเองOpenOptionเขาจะทำได้


กรณี 'แบบอักษร' ของคุณยังคงคลุมเครือหากมีการขอ Enums เดียวกันสองคำขอ คำตอบที่เป็นที่ยอมรับในการแก้ไขปัญหาที่เป็นสิ่งที่หลายภาษาเรียกชื่อพารามิเตอร์ สนับสนุนลายเซ็นเมธอดนั้นหรือดีกว่า
aaaaaa

1
@aaaaaa ฉันไม่เห็นหลายกรณีที่นวกรรมิกจะใช้สองกรณีเดียวกันenumโดยไม่ต้องใช้varargsหรือ a Setเพื่อหาจำนวนโดยพลการ
Jeffrey

@aaaaaa ปัญหาหลักของพารามิเตอร์ที่มีชื่อจะขึ้นอยู่กับรายละเอียดการใช้งาน (ชื่อของพารามิเตอร์) interface Foo { public void bar(String baz); }ฉันสามารถทำให้อินเตอร์เฟซ มีคนสร้างคลาสที่เรียกbar: someFoo.bar(baz = "hello");. ฉันจะเปลี่ยนลายเซ็นของการFoo::bar public void bar(String foobar)ตอนนี้คนที่เรียกsomeFooจะต้องแก้ไขรหัสของพวกเขาหากพวกเขายังต้องการให้มันทำงาน
Jeffrey

ฉันจำไม่ได้ว่าเห็น enum ประเภทต่อเนื่องเช่นกัน แต่คิดว่าคนทั่วไปอาจเป็น DAY_OF_WEEK หรืออะไรทำนองนั้น และข้อดีของอินเทอร์เฟซ - ก็ไม่ได้คิดเช่นนั้น โดยส่วนตัวแล้วฉันจะใช้ปัญหานั้นมากกว่าความกำกวมที่เกิดจากพารามิเตอร์ที่ไม่มีชื่อทำให้ต้องมีการสนับสนุน IDE ที่แข็งแกร่ง ฉันเข้าใจว่าเป็นการตัดสินใจที่ใช้วิจารณญาณและการเปลี่ยนแปลงการแบ่ง API เป็นสิ่งที่ต้องพิจารณาอย่างจริงจัง
aaaaaa

26

มีคำตอบที่ดีมากมายที่นี่ แต่ไม่มีใครพูดถึงว่ามีการใช้งานที่ปรับให้เหมาะสมที่สุดของคลาส / อินเตอร์เฟส API การรวบรวมโดยเฉพาะสำหรับ enums :

คลาสที่ระบุเฉพาะ enum เหล่านี้ยอมรับEnumอินสแตนซ์EnumMapเท่านั้น (ยอมรับเฉพาะEnums เป็นคีย์เท่านั้น) และเมื่อใดก็ตามที่เป็นไปได้

สิ่งนี้หมายความว่า?

หากEnumประเภทของเราไม่มีองค์ประกอบอีก 64 องค์ประกอบ ( Enumตัวอย่างในชีวิตจริงส่วนใหญ่จะผ่านคุณสมบัตินี้) การใช้งานจะเก็บองค์ประกอบไว้ในlongค่าเดียวแต่ละEnumอินสแตนซ์ที่มีปัญหาจะเชื่อมโยงกับบิตของความยาว 64 บิตlongนี้ การเพิ่มองค์ประกอบให้กับEnumSetเพียงแค่การตั้งค่าบิตที่เหมาะสมถึง 1 การลบมันเป็นเพียงการตั้งค่าบิตที่ 0 การทดสอบว่าองค์ประกอบอยู่ในนั้นSetเป็นเพียงการทดสอบ bitmask หนึ่ง! ตอนนี้คุณต้องรักEnumสิ่งนี้!


1
ฉันเคยรู้เกี่ยวกับสองสิ่งนี้มาก่อน แต่ฉันเพิ่งเรียนรู้มากมายจากWhat does this mean?หัวข้อของคุณ ฉันรู้ว่ามีการแบ่งในการใช้งานที่ขนาด 64 แต่ฉันไม่รู้จริง ๆ ว่าทำไม
Christopher Rucinski

15

ตัวอย่าง:

public class CurrencyDenom {
   public static final int PENNY = 1;
 public static final int NICKLE = 5;
 public static final int DIME = 10;
public static final int QUARTER = 25;}

ข้อ จำกัด ของค่าคงที่ของจาวา

1) ไม่มีประเภทความปลอดภัย : ก่อนอื่นมันไม่ปลอดภัยประเภท; คุณสามารถกำหนดค่า int ที่ถูกต้องให้กับ int เช่น 99 แม้ว่าจะไม่มีเหรียญที่จะแสดงค่านั้น

2) No Printing ที่มีความหมาย : ค่าการพิมพ์ของค่าคงที่ใด ๆ เหล่านี้จะพิมพ์ค่าตัวเลขแทนชื่อเหรียญที่มีความหมายเช่นเมื่อคุณพิมพ์ NICKLE มันจะพิมพ์ "5" แทน "NICKLE"

3) ไม่มีเนมสเปซ : ในการเข้าถึงค่าคงที่ currencyDenom เราจำเป็นต้องใช้ชื่อคลาสของคำนำหน้าเช่น CurrencyDenom.PENNY แทนที่จะใช้เพียง PENNY แม้ว่าจะสามารถทำได้โดยใช้การนำเข้าแบบคงที่ใน JDK 1.5

ข้อได้เปรียบของ enum

1) Enums ใน Java เป็นประเภทที่ปลอดภัยและมีชื่อพื้นที่ของตัวเอง หมายความว่า enum ของคุณจะมีประเภทเช่น "สกุลเงิน" ในตัวอย่างด้านล่างและคุณไม่สามารถกำหนดค่าอื่นใดนอกเหนือจากที่ระบุไว้ในค่าคงที่ Enum

public enum Currency {PENNY, NICKLE, DIME, QUARTER};

Currency coin = Currency.PENNY; coin = 1; //compilation error

2) Enum ใน Java เป็นประเภทการอ้างอิงเช่นคลาสหรืออินเทอร์เฟซและคุณสามารถกำหนด constructor วิธีการและตัวแปรภายใน java Enum ซึ่งทำให้มีประสิทธิภาพมากกว่า Enum ใน C และ C ++ ดังที่แสดงในตัวอย่างถัดไปของ Java Enum type

3) คุณสามารถระบุค่าของค่าคงที่ enum ณ เวลาที่สร้างดังแสดงในตัวอย่างด้านล่าง: สกุลเงินสาธารณะ enum {PENNY (1), NICKLE (5), DIME (10), QUARTER (25)}; แต่สำหรับสิ่งนี้ในการทำงานคุณจำเป็นต้องกำหนดตัวแปรสมาชิกและตัวสร้างเนื่องจาก PENNY (1) กำลังเรียกตัวสร้างที่ยอมรับค่า int ดูตัวอย่างด้านล่าง

public enum Currency {
    PENNY(1), NICKLE(5), DIME(10), QUARTER(25);
    private int value;

    private Currency(int value) {
            this.value = value;
    }
}; 

การอ้างอิง: https://javarevisited.blogspot.com/2011/08/enum-in-java-example-tutorial.html


11

ประโยชน์แรกของ enums ดังที่คุณได้สังเกตเห็นแล้วคือความเรียบง่ายของไวยากรณ์ แต่จุดหลักของ enums คือการจัดให้มีชุดของค่าคงที่ที่รู้จักกันดีซึ่งโดยค่าเริ่มต้นจัดรูปแบบช่วงและช่วยในการวิเคราะห์รหัสที่ครอบคลุมมากขึ้นผ่านการตรวจสอบความปลอดภัยประเภทและค่า

คุณลักษณะเหล่านั้นของ enums ช่วยทั้งโปรแกรมเมอร์และคอมไพเลอร์ ตัวอย่างเช่นสมมติว่าคุณเห็นฟังก์ชั่นที่รับจำนวนเต็ม จำนวนเต็มที่อาจหมายถึงอะไร คุณสามารถส่งผ่านค่าชนิดใด คุณไม่รู้จริง ๆ ทันที แต่ถ้าคุณเห็นฟังก์ชั่นที่ยอมรับ enum คุณจะรู้ได้ว่าค่าที่เป็นไปได้ทั้งหมดที่คุณสามารถส่งผ่านได้เป็นอย่างดี

สำหรับคอมไพเลอร์ enums ช่วยในการกำหนดช่วงของค่าและถ้าคุณไม่ได้กำหนดค่าพิเศษให้กับสมาชิก enum พวกเขาอยู่ในช่วงตั้งแต่ 0 ขึ้นไป ซึ่งช่วยในการติดตามข้อผิดพลาดในรหัสโดยอัตโนมัติผ่านการตรวจสอบความปลอดภัยของประเภทและอื่น ๆ ตัวอย่างเช่นคอมไพเลอร์อาจเตือนคุณว่าคุณไม่ได้จัดการค่า enum ที่เป็นไปได้ทั้งหมดในคำสั่ง switch ของคุณ (เช่นเมื่อคุณไม่มีตัวdefaultพิมพ์เล็กและจัดการค่า enum เพียงค่าเดียวเท่านั้น) นอกจากนี้ยังเตือนคุณเมื่อคุณแปลงจำนวนเต็มตามอำเภอใจเป็น enum เนื่องจากช่วงของค่า enum น้อยกว่าจำนวนเต็มและในทางกลับกันอาจทำให้เกิดข้อผิดพลาดในฟังก์ชันที่ไม่ยอมรับจำนวนเต็มจริง ๆ นอกจากนี้การสร้างตารางการกระโดดสำหรับสวิทช์จะกลายเป็นเรื่องง่ายขึ้นเมื่อค่าจาก 0 ขึ้นไป

สิ่งนี้ไม่เพียงเป็นความจริงสำหรับ Java แต่สำหรับภาษาอื่นที่มีการตรวจสอบประเภทที่เข้มงวดเช่นกัน C, C ++, D, C # เป็นตัวอย่างที่ดี


4

Enum ที่เป็นที่สิ้นสุด implictly กับการก่อสร้างภาคเอกชนทุกค่าของมันเป็นชนิดเดียวกันหรือประเภทย่อยคุณสามารถได้รับทุกค่าของการใช้values()ที่ได้รับของname()หรือordinal()ค่าหรือคุณสามารถมองขึ้น enum จากจำนวนหรือชื่อ

นอกจากนี้คุณยังสามารถกำหนดคลาสย่อยได้ (แม้จะเป็นครั้งสุดท้าย แต่สิ่งที่คุณไม่สามารถทำได้)

enum Runner implements Runnable {
    HI {
       public void run() {
           System.out.println("Hello");
       }
    }, BYE {
       public void run() {
           System.out.println("Sayonara");
       }
       public String toString() {
           return "good-bye";
       }
    }
 }

 class MYRunner extends Runner // won't compile.

4

ประโยชน์ enum:

  1. Enums เป็นเขตปลอดภัยชนิดคงที่ไม่ใช่
  2. มีค่าจำนวน จำกัด (เป็นไปไม่ได้ที่จะผ่านค่า enum ที่ไม่มีอยู่หากคุณมีฟิลด์คลาสแบบสแตติกคุณสามารถทำผิดพลาดได้)
  3. แต่ละ enum สามารถมีคุณสมบัติได้หลายอย่าง (field / getters) ที่ได้รับมอบหมาย - encapsulation วิธีการง่ายๆเช่น: YEAR.toSeconds () หรือที่คล้ายกัน เปรียบเทียบ: Colors.RED.getHex () กับ Colors.toHex (Colors.RED)

"เช่นความสามารถในการกำหนดองค์ประกอบ enum ให้ได้อย่างง่ายดาย"

enum EnumX{
  VAL_1(1),
  VAL_200(200);
  public final int certainValue;
  private X(int certainValue){this.certainValue = certainValue;}
}

"และดังนั้นความสามารถในการแปลงจำนวนเต็มเป็น enum โดยไม่มีความพยายามพอสมควร" เพิ่มวิธีการแปลง int เป็น enum ซึ่งทำเช่นนั้น เพียงแค่เพิ่ม HashMap คง <จำนวนเต็ม EnumX> ที่มีการทำแผนที่จาวา enum

หากคุณต้องการแปลง ord = VAL_200.ordinal () กลับไปที่ val_200 ให้ใช้: EnumX.values ​​() [ord]


3

ข้อแตกต่างที่สำคัญอีกประการหนึ่งคือคอมไพเลอร์ java ใช้static finalฟิลด์ชนิดดั้งเดิมและสตริงเป็นตัวอักษร หมายความว่าค่าคงที่เหล่านี้กลายเป็นแบบอินไลน์ มันคล้ายกับC/C++ #definepreprocessor ดูคำถาม SOนี้ นี่ไม่ใช่กรณีที่มี enums



2

ข้อได้เปรียบที่ใหญ่ที่สุดคือ enum Singletons ง่ายต่อการเขียนและปลอดภัยสำหรับเธรด:

public enum EasySingleton{
    INSTANCE;
}

และ

/**
* Singleton pattern example with Double checked Locking
*/
public class DoubleCheckedLockingSingleton{
     private volatile DoubleCheckedLockingSingleton INSTANCE;

     private DoubleCheckedLockingSingleton(){}

     public DoubleCheckedLockingSingleton getInstance(){
         if(INSTANCE == null){
            synchronized(DoubleCheckedLockingSingleton.class){
                //double checking Singleton instance
                if(INSTANCE == null){
                    INSTANCE = new DoubleCheckedLockingSingleton();
                }
            }
         }
         return INSTANCE;
     }
}

ทั้งสองมีความคล้ายคลึงกันและมันจัดการ Serialization ด้วยตัวเองโดยการนำ

//readResolve to prevent another instance of Singleton
    private Object readResolve(){
        return INSTANCE;
    }

มากกว่า


0

ฉันคิดว่าenumไม่สามารถทำได้finalเพราะในคอมไพเลอร์ประทุนจะสร้างคลาสย่อยสำหรับแต่ละรายการenumรายการ

ข้อมูลเพิ่มเติมจากแหล่งที่มา


ภายในพวกเขาจะไม่สุดท้ายเพราะ - ตามที่คุณพูด - สามารถ subclassed ภายใน แต่อนิจจาคุณไม่สามารถคลาสย่อยเหล่านั้นด้วยตัวคุณเองเช่นสำหรับการขยายด้วยค่าของตัวเอง
glglgl

0

มีข้อดีมากมายของ enums ที่โพสต์ที่นี่และฉันกำลังสร้าง enums ดังกล่าวในขณะนี้ตามที่ถามในคำถาม แต่ฉันมี enum ที่มี 5-6 ฟิลด์

enum Planet{
EARTH(1000000, 312312321,31232131, "some text", "", 12),
....
other planets
....

ในกรณีเหล่านี้เมื่อคุณมีหลายฟิลด์ใน enums มันยากมากที่จะเข้าใจว่าค่าใดเป็นของฟิลด์ใดตามที่คุณต้องการดูคอนสตรัคเตอร์และลูกตา

เรียนกับstatic finalค่าคงที่และการใช้Builderรูปแบบเพื่อสร้างวัตถุดังกล่าวทำให้อ่านง่ายขึ้น แต่คุณจะสูญเสียข้อได้เปรียบอื่น ๆ ทั้งหมดของการใช้ enum หากคุณต้องการ ข้อเสียอย่างหนึ่งของคลาสดังกล่าวคือคุณต้องเพิ่มPlanetวัตถุด้วยตนเองลงในlist/setของPlanets.

ฉันยังคงต้องการ enum กว่าระดับดังกล่าวเป็นvalues()มาในสะดวกและคุณไม่เคยรู้ว่าถ้าคุณต้องการที่จะใช้ในswitchหรือEnumSetหรือEnumMapในอนาคต :)


0

เหตุผลหลัก: Enums ช่วยให้คุณเขียนโค้ดที่มีโครงสร้างที่ดีซึ่งความหมายเชิงความหมายของพารามิเตอร์นั้นชัดเจนและพิมพ์อย่างยิ่งในเวลารวบรวม - ด้วยเหตุผลทั้งหมดที่มีคำตอบอื่นให้ไว้

ตอบแทน:ใน Java ออกจากกล่องสมาชิกของ Enum เป็นที่สิ้นสุด ปกติแล้วมันจะดีเพราะช่วยในเรื่องความปลอดภัยและการทดสอบ แต่ในบางสถานการณ์มันอาจเป็นข้อเสียเปรียบเช่นถ้าคุณกำลังขยายรหัสฐานที่มีอยู่อาจจะมาจากห้องสมุด ในทางตรงกันข้ามหากข้อมูลเดียวกันอยู่ในคลาสที่มีเขตข้อมูลแบบคงที่คุณสามารถเพิ่มอินสแตนซ์ใหม่ของคลาสนั้นได้ในขณะรันไทม์ (คุณอาจต้องเขียนโค้ดเพื่อเพิ่มสิ่งเหล่านี้ใน Iterable ที่คุณมีสำหรับคลาสนั้น) แต่พฤติกรรมของ Enums นี้สามารถเปลี่ยนแปลงได้: โดยใช้การสะท้อนคุณสามารถเพิ่มสมาชิกใหม่ที่รันไทม์หรือแทนที่สมาชิกที่มีอยู่ถึงแม้ว่าสิ่งนี้อาจจะทำได้เฉพาะในสถานการณ์พิเศษที่ไม่มีทางเลือกอื่น ๆ : นั่นคือโซลูชันแฮ็กและอาจทำให้เกิดปัญหาที่ไม่คาดคิด ดูคำตอบของฉันฉันสามารถเพิ่มและลบองค์ประกอบของการแจงนับที่รันไทม์ในชวา

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.