Java menggunakan enum dengan pernyataan switch

106

Saya telah melihat berbagai Tanya Jawab tentang SO yang mirip dengan pertanyaan ini tetapi belum menemukan solusi.

Yang saya miliki adalah enum yang mewakili berbagai cara untuk melihat Panduan TV ...

Di Applicationkelas NDroid

static enum guideView {
    GUIDE_VIEW_SEVEN_DAY,
    GUIDE_VIEW_NOW_SHOWING,
    GUIDE_VIEW_ALL_TIMESLOTS
}

... ketika pengguna mengubah tampilan yang diterima event handler intdari 0-2 dan saya ingin melakukan sesuatu seperti ini ...

Dalam Activity onClick(DialogInterface dialog, int which)penanganan peristiwa Android

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

Saya sudah terbiasa dengan C # enums dan pernyataan pilih / case yang akan memungkinkan sesuatu seperti di atas dan saya tahu Java melakukan sesuatu secara berbeda tetapi saya tidak dapat memahami apa yang perlu saya lakukan.

Apakah saya harus menggunakan ifpernyataan? Kemungkinan hanya akan ada 3 pilihan jadi saya bisa melakukannya tapi saya bertanya-tanya bagaimana itu bisa dilakukan dengan switch-case di Java.

EDIT Maaf saya tidak sepenuhnya memperluas masalah ini karena saya melihatnya sebagai masalah Java umum. Saya telah menambahkan pertanyaan untuk menjelaskan lebih jauh.

Tidak ada apa pun yang khusus Android, itulah sebabnya saya tidak menandainya sebagai Android tetapi enum didefinisikan di Applicationkelas dan kode di mana saya tidak ingin sakelar di Activity. Enumnya statis karena saya perlu mengaksesnya dari beberapa Aktivitas.

Squonk
sumber
1
Seharusnya hanya case GUIDE_VIEW_SEVEN_DAYsetelah impor yang tepat; permasalahan apa yang kamu hadapi?
Dave Newton
Tidak bisakah Anda membuat event handler Anda menerima enum? Selain itu, mungkin ini akan membantu: stackoverflow.com/questions/5292790/…
Brian Roach
@ Dave: Ups maaf, saya telah mengoreksi kode untuk menunjukkan bagaimana itu. Eclipse memberi saya kesalahan Type Mismatch yang mengatakan itu tidak dapat dikonversi dari guideView ke int.
Squonk
@ Brian: Ini adalah aplikasi Android dan event handler ( OnClickListener ) didefinisikan oleh DialogInterfaceantarmuka yang harus saya implementasikan.
Squonk
@MisterSquonk Oh, saya merindukan Anda mendapatkannya dari int - maaf, lihat jawaban Ophidian, meskipun saya akan meletakkan fungsionalitasnya di enum.
Dave Newton

Jawaban:

162

Bagian yang Anda lewatkan adalah mengonversi dari integer ke enum type-safe. Java tidak akan melakukannya secara otomatis. Ada beberapa cara untuk melakukan ini:

  1. Gunakan daftar int final statis daripada enum tipe-aman dan aktifkan nilai int yang Anda terima (ini adalah pendekatan pra-Java 5)
  2. Aktifkan baik nilai id yang ditentukan (seperti yang dijelaskan oleh heneryville ) atau nilai ordinal dari nilai enum; yaituguideView.GUIDE_VIEW_SEVEN_DAY.ordinal()
  3. Tentukan nilai enum yang diwakili oleh nilai int dan kemudian aktifkan nilai 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;
        }
    }

    Anda mungkin merasa lebih membantu / lebih sedikit kesalahan yang rawan untuk menulis valueOfimplementasi kustom yang menggunakan nilai integer Anda sebagai argumen untuk menyelesaikan nilai enum yang sesuai dan memungkinkan Anda memusatkan pemeriksaan batas.

Ophidian
sumber
Terimakasih banyak. Butuh beberapa saat untuk mengerjakannya ke dalam kode saya, tetapi sekarang berfungsi dengan baik dengan kode contoh yang Anda posting. 6 tahun dengan C # dan 1 tahun dengan Java - tidak sering saya menemukan sesuatu yang membuat saya bingung. Begitu banyak kemiripan tapi sesekali seperti ini yang sangat berbeda sekali. Saya tidak akan melupakan yang ini dengan terburu-buru. :-)
Squonk
2
Anda memerlukan nama enum yang tidak memenuhi syarat dalam pernyataan kasus, jadi case GuideView.SEVEN_DAY:berikan kesalahan kompilasi, seharusnya begitu case SEVEN_DAY:.
haridsv
Luar biasa bro !!
Neo
42

Jika whichViewmerupakan objek dari GuideView Enum, berikut ini berfungsi dengan baik. Harap dicatat bahwa tidak ada kualifikasi untuk konstanta setelahnya case.

switch (whichView) {
    case SEVEN_DAY:
        ...
        break;
    case NOW_SHOWING:
        ...
        break;
}
Dhanushka
sumber
4
bagaimana ini mungkin ?!
Jes Chergui
12

Enum tidak boleh memenuhi syarat dalam label kasus seperti yang Anda miliki NDroid.guideView.GUIDE_VIEW_SEVEN_DAY, sebaliknya Anda harus menghapus kualifikasi dan penggunaanGUIDE_VIEW_SEVEN_DAY

Piyush Mattoo
sumber
Lebih suka yang ini. Sederhana!
Ninja Malas
5

Saya suka beberapa penggunaan Java enum:

  1. .name () memungkinkan Anda mengambil nama enum dalam String.
  2. .ordinal () memungkinkan Anda mendapatkan nilai integer, berbasis 0.
  3. Anda dapat melampirkan parameter nilai lain dengan setiap enum.
  4. dan, tentu saja, sakelar diaktifkan.

enum dengan parameter nilai:

    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); 
        ...
    }

contoh saklar:

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

Ini harus bekerja dengan cara yang Anda gambarkan. Kesalahan apa yang Anda dapatkan? Jika Anda bisa menyisipkan kode Anda itu akan membantu.

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

EDIT: Apakah Anda yakin ingin menentukan enum statis? Itu kedengarannya tidak benar bagi saya. Enum sama seperti objek lainnya. Jika kode Anda dikompilasi dan dijalankan tetapi memberikan hasil yang salah, mungkin inilah penyebabnya.

SystemParadox
sumber
"Jenis enum bertingkat secara implisit statis. Ini diizinkan untuk secara eksplisit menyatakan jenis enum bertingkat menjadi statis." - JLS §8.9 .
trashgod
@trashgod, memang- tapi saya akan selalu menggunakan deklarasi implisit untuk menghindari kebingungan karena itu sebenarnya IMO yang lebih jelas. Sebuah enum statis global (seperti yang saya asumsikan) mungkin salah dalam banyak kasus.
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
Jaya
sumber
Itu hanya berfungsi jika Anda tidak mendapatkan data Anda secara eksternal. Karena OP mengatakan yang mengembalikan nilai 1, 2, 3 bukan JENIS metode Anda tidak akan bekerja tanpa kasus sakelar terbalik yang mengambil 1, 2, 3 dan mengembalikan JENIS sebelum masuk ke kotak sakelar yang dia daftarkan ..
WORMSS
2

Contoh fungsi asosiatif singkat:

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 "";
    }
}

Seperti yang dikatakan @Dhanushka, hilangkan kualifikasi di dalam "switch" adalah kuncinya.

Auston
sumber
1

Saya melakukannya seperti

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;   
}

Dan gunakan dalam Pernyataan Switch

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

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

case Preparing:
case Playing:

    playPause.setBackgroundResource(R.drawable.selpause);
    break;    
}
Zar E Ahmer
sumber