Java โดยใช้ enum พร้อมคำสั่ง switch


106

ฉันได้ดู Q & As ต่างๆเกี่ยวกับ SO คล้ายกับคำถามนี้ แต่ไม่พบวิธีแก้ปัญหา

สิ่งที่ฉันมีคือ enum ซึ่งแสดงถึงวิธีต่างๆในการดูทีวีไกด์ ...

ในApplicationคลาสNDroid

static enum guideView {
    GUIDE_VIEW_SEVEN_DAY,
    GUIDE_VIEW_NOW_SHOWING,
    GUIDE_VIEW_ALL_TIMESLOTS
}

... เมื่อผู้ใช้เปลี่ยนมุมมองตัวจัดการเหตุการณ์จะได้รับintจาก 0-2 และฉันต้องการทำสิ่งนี้ ...

ในActivity onClick(DialogInterface dialog, int which)ตัวจัดการเหตุการณ์Android

// 'which' is an int from 0-2
switch (which) {
    case NDroid.guideView.GUIDE_VIEW_SEVEN_DAY:
    ...
    break;
}

ฉันคุ้นเคยกับ C # enums และคำสั่ง select / case ซึ่งจะอนุญาตบางอย่างเช่นข้างต้นและฉันรู้ว่า Java ทำสิ่งต่าง ๆ แต่ฉันไม่เข้าใจว่าต้องทำอะไร

ฉันจะต้องใช้ifงบ? อาจจะมีเพียง 3 ตัวเลือกเท่านั้นดังนั้นฉันจึงสามารถทำได้ แต่ฉันสงสัยว่ามันจะทำได้อย่างไรกับสวิตช์เคสใน Java

แก้ไขขออภัยฉันไม่ได้ขยายความเกี่ยวกับปัญหานี้ทั้งหมดเนื่องจากฉันมองว่าปัญหานี้เป็นปัญหาทั่วไปของ Java ฉันได้เพิ่มคำถามเพื่ออธิบายเพิ่มเติมเล็กน้อย

ไม่มีอะไรที่เฉพาะเจาะจงสำหรับ Android ซึ่งเป็นสาเหตุที่ฉันไม่ได้แท็กเป็น Android แต่ enum ถูกกำหนดไว้ในApplicationคลาสและรหัสที่ฉันไม่ต้องการให้สวิตช์อยู่ในActivityไฟล์. enum เป็นแบบคงที่เนื่องจากฉันต้องการเข้าถึงจากหลายกิจกรรม


1
ควรcase GUIDE_VIEW_SEVEN_DAYหลังจากการนำเข้าที่เหมาะสม คุณมีปัญหาอะไร
Dave Newton

คุณไม่สามารถทำให้ตัวจัดการเหตุการณ์ของคุณได้รับ enum ได้หรือไม่? นอกเหนือจากนั้นสิ่งนี้อาจช่วยได้: stackoverflow.com/questions/5292790/…
Brian Roach

@ Dave: อ๊ะขออภัยฉันได้แก้ไขรหัสเพื่อแสดงว่าเป็นอย่างไร Eclipse ทำให้ฉันมีข้อผิดพลาด Type Mismatch โดยบอกว่าไม่สามารถแปลงจาก guideView เป็น int ได้
Squonk

@ ไบรอัน: นี่คือแอพ Android และตัวจัดการเหตุการณ์ ( OnClickListener ) ถูกกำหนดโดยDialogInterfaceอินเทอร์เฟซที่ฉันต้องใช้
Squonk

@MisterSquonk โอ้ฉันพลาดที่คุณได้รับจาก int - ขอโทษดูคำตอบของ Ophidian แม้ว่าฉันจะใส่ฟังก์ชันการทำงานไว้ใน enum
Dave Newton

คำตอบ:


162

ส่วนที่คุณขาดหายไปคือการแปลงจากจำนวนเต็มเป็น enum ชนิดปลอดภัย Java จะไม่ทำโดยอัตโนมัติ มีสองวิธีที่คุณสามารถทำได้:

  1. ใช้รายการของ ints สุดท้ายแบบคงที่แทนที่จะเป็น enum ชนิดปลอดภัยและเปิดค่า int ที่คุณได้รับ (นี่คือแนวทางก่อน Java 5)
  2. เปิดค่ารหัสที่ระบุ ( ตามที่เฮนเนอรีวิลล์อธิบาย ) หรือค่าลำดับของค่า enum กล่าวคือguideView.GUIDE_VIEW_SEVEN_DAY.ordinal()
  3. กำหนดค่า enum ที่แสดงด้วยค่า int จากนั้นเปิดค่า enum

    enum GuideView {
        SEVEN_DAY,
        NOW_SHOWING,
        ALL_TIMESLOTS
    }
    
    // Working on the assumption that your int value is 
    // the ordinal value of the items in your enum
    public void onClick(DialogInterface dialog, int which) {
        // do your own bounds checking
        GuideView whichView = GuideView.values()[which];
        switch (whichView) {
            case SEVEN_DAY:
                ...
                break;
            case NOW_SHOWING:
                ...
                break;
        }
    }

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


ขอบคุณมาก. ฉันใช้เวลาสักพักในการทำงานกับโค้ดของฉัน แต่ตอนนี้ใช้งานได้ดีกับโค้ดตัวอย่างที่คุณโพสต์ 6 ปีกับ C # และ 1 ปีกับ Java - ไม่บ่อยนักที่ฉันจะเจออะไรที่ทำให้ฉันสะดุด มีความคล้ายคลึงกันมาก แต่บางครั้งก็มีลักษณะเช่นนี้ซึ่งแตกต่างกันมาก ฉันจะไม่ลืมเรื่องนี้โดยเร็ว :-)
Squonk

2
คุณจำเป็นต้องมีชื่อ enum อย่างไม่มีเงื่อนไขในงบกรณีเพื่อให้รวบรวมข้อผิดพลาดที่มันควรจะเป็นcase GuideView.SEVEN_DAY: case SEVEN_DAY:
haridsv

สุดยอดครับพี่ !!
นีโอ

42

ถ้าwhichViewเป็นวัตถุของ GuideView Enum การติดตามจะทำงานได้ดี caseโปรดทราบว่ามีการคัดเลือกอย่างต่อเนื่องหลังจากที่ไม่มี

switch (whichView) {
    case SEVEN_DAY:
        ...
        break;
    case NOW_SHOWING:
        ...
        break;
}

4
เป็นไปได้ยังไง?!
Jes Chergui

12

enums ไม่ควรมีคุณสมบัติภายในป้ายกำกับเคสเช่นเดียวกับสิ่งที่คุณมีNDroid.guideView.GUIDE_VIEW_SEVEN_DAYแต่คุณควรลบคุณสมบัติและการใช้งานGUIDE_VIEW_SEVEN_DAY


ชอบอันนี้ เรียบง่าย!
Lazy Ninja

5

ฉันชอบการใช้ Java enum เล็กน้อย:

  1. .name () อนุญาตให้คุณดึงชื่อ enum ใน String
  2. .ordinal () ช่วยให้คุณได้รับค่าจำนวนเต็มโดยใช้ 0
  3. คุณสามารถแนบพารามิเตอร์ค่าอื่น ๆ กับแต่ละ enum
  4. และแน่นอนเปิดใช้งานสวิตช์

enum พร้อมพารามิเตอร์ค่า:

    enum StateEnum {
        UNDEFINED_POLL  ( 1 * 1000L,       4 * 1000L),
        SUPPORT_POLL    ( 1 * 1000L,       5 * 1000L),
        FAST_POLL       ( 2 * 1000L,  4 * 60 * 1000L),
        NO_POLL         ( 1 * 1000L,       6 * 1000L); 
        ...
    }

เปลี่ยนตัวอย่าง:

private void queuePoll(StateEnum se) {
    // debug print se.name() if needed
    switch (se) {
        case UNDEFINED_POLL:
            ...
            break;
        case SUPPORT_POLL:
            ...
            break;

3

สิ่งนี้ควรได้ผลในลักษณะที่คุณอธิบาย คุณได้รับข้อผิดพลาดอะไร หากคุณสามารถวางโค้ดของคุณได้ซึ่งจะช่วยได้

http://download.oracle.com/javase/tutorial/java/javaOO/enum.html

แก้ไข: คุณแน่ใจหรือไม่ว่าต้องการกำหนด enum คงที่? มันไม่ถูกต้องสำหรับฉัน enum ก็เหมือนกับวัตถุอื่น ๆ หากโค้ดของคุณรวบรวมและทำงาน แต่ให้ผลลัพธ์ที่ไม่ถูกต้องนี่อาจเป็นสาเหตุ


"ประเภท enum ซ้อนกันจะคงที่โดยปริยายมันเป็น permissable อย่างชัดเจนประกาศประเภท enum ซ้อนกันจะเป็นแบบคงที่.." - JLS §8.9
trashgod

@trashgod แน่นอน - แต่ฉันมักจะใช้การประกาศโดยปริยายเพื่อหลีกเลี่ยงความสับสนเนื่องจากเป็น IMO ที่ชัดเจนมากขึ้น enum คงที่ทั่วโลก (ซึ่งเป็นสิ่งที่ฉันคิดว่านี่คือ) อาจผิดในกรณีส่วนใหญ่
SystemParadox

2
enumerations accessing is very simple in switch case

private TYPE currentView;

//declaration of enum 
public enum TYPE {
        FIRST, SECOND, THIRD
    };

//handling in switch case
switch (getCurrentView())
        {
        case FIRST:
            break;
        case SECOND:
            break;
        case THIRD:
            break;
        }

//getter and setter of the enum
public void setCurrentView(TYPE currentView) {
        this.currentView = currentView;
    }

    public TYPE getCurrentView() {
        return currentView;
    }

//usage of setting the enum 
setCurrentView(TYPE.FIRST);

avoid the accessing of TYPE.FIRST.ordinal() it is not recommended always

จะใช้ได้เฉพาะในกรณีที่คุณไม่ได้รับข้อมูลจากภายนอก เนื่องจาก OP บอกว่าส่งคืนค่า 1, 2, 3 ไม่ใช่ TYPE วิธีของคุณจะไม่ทำงานหากไม่มีกรณีสวิตช์ย้อนกลับที่ใช้เวลา 1, 2, 3 และส่งคืน TYPE ก่อนที่จะเข้าสู่กรณีสวิตช์ที่เขาระบุไว้ ..
WORMSS

2

ตัวอย่างฟังก์ชันการเชื่อมโยงแบบสั้น:

public String getIcon(TipoNotificacao tipo)
{
    switch (tipo){
        case Comentou : return "fa fa-comments";
        case ConviteEnviou : return "icon-envelope";
        case ConviteAceitou : return "fa fa-bolt";
        default: return "";
    }
}

เช่นเดียวกับที่ @Dhanushka กล่าวว่าการละเว้นคุณสมบัติภายใน "สวิตช์" เป็นกุญแจสำคัญ


1

ฉันกำลังทำมันเหมือน

public enum State
{
    // Retrieving, // the MediaRetriever is retrieving music //
    Stopped, // media player is stopped and not prepared to play
    Preparing, // media player is preparing...
    Playing, // playback active (media player ready!). (but the media player
                // may actually be
                // paused in this state if we don't have audio focus. But we
                // stay in this state
                // so that we know we have to resume playback once we get
                // focus back)
    Paused; // playback paused (media player ready!)

    //public final static State[] vals = State.values();//copy the values(), calling values() clones the array

};

public State getState()
{
        return mState;   
}

และใช้ใน Switch Statement

switch (mService.getState())
{
case Stopped:
case Paused:

    playPause.setBackgroundResource(R.drawable.selplay);
    break;

case Preparing:
case Playing:

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