Java sử dụng enum với câu lệnh switch


106

Tôi đã xem nhiều phần Hỏi & Đáp khác nhau trên SO tương tự như câu hỏi này nhưng chưa tìm ra giải pháp.

Những gì tôi có là một enum đại diện cho các cách khác nhau để xem Hướng dẫn TV ...

Trong Applicationlớp NDroid

static enum guideView {
    GUIDE_VIEW_SEVEN_DAY,
    GUIDE_VIEW_NOW_SHOWING,
    GUIDE_VIEW_ALL_TIMESLOTS
}

... khi người dùng thay đổi chế độ xem, trình xử lý sự kiện sẽ nhận được giá trị inttừ 0-2 và tôi muốn làm điều gì đó như thế này ...

Trong Activity onClick(DialogInterface dialog, int which)trình xử lý sự kiện Android

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

Tôi đã quen với C # enums và các câu lệnh select / case sẽ cho phép một cái gì đó như trên và tôi biết Java làm những việc khác nhau nhưng tôi không thể hiểu được những gì tôi cần làm.

Tôi sẽ phải sử dụng đến các iftuyên bố? Có thể sẽ chỉ có 3 lựa chọn để tôi có thể làm điều đó nhưng tôi tự hỏi làm thế nào nó có thể được thực hiện với switch-case trong Java.

BIÊN TẬP Xin lỗi, tôi không mở rộng hoàn toàn về vấn đề này vì tôi đang xem nó là một vấn đề Java chung chung. Tôi đã thêm vào câu hỏi để giải thích thêm một chút.

Không có bất cứ thứ gì dành riêng cho Android, đó là lý do tại sao tôi không gắn thẻ nó là Android nhưng enum được xác định trong Applicationlớp và mã nơi tôi không có công tắc Activity. Enum là tĩnh vì tôi cần truy cập nó từ nhiều Hoạt động.


1
Chỉ nên case GUIDE_VIEW_SEVEN_DAYsau khi nhập khẩu thích hợp; Có vấn đề gì bạn đang có?
Dave Newton

Bạn không thể làm cho trình xử lý sự kiện của bạn nhận được một enum? Bên cạnh đó, có lẽ điều này sẽ giúp: stackoverflow.com/questions/5292790/...
Brian Roach

@Dave: Rất tiếc, tôi đã sửa mã để hiển thị như thế nào. Eclipse đang cho tôi lỗi Loại không khớp nói rằng nó không thể chuyển đổi từ guideView thành int.
Squonk

@Brian: Đây là một ứng dụng Android và trình xử lý sự kiện ( OnClickListener ) được xác định bởi DialogInterfacegiao diện mà tôi phải triển khai.
Squonk

@MisterSquonk Ồ, tôi nhớ bạn đã lấy nó từ một int - xin lỗi, hãy xem câu trả lời của Ophidian, mặc dù tôi đã đặt chức năng này trong enum.
Dave Newton

Câu trả lời:


162

Phần bạn đang thiếu là chuyển đổi từ số nguyên sang kiểu enum an toàn. Java sẽ không tự động làm điều đó. Có một số cách bạn có thể thực hiện:

  1. Sử dụng danh sách các int cuối cùng tĩnh thay vì một enum kiểu an toàn và bật giá trị int mà bạn nhận được (đây là cách tiếp cận trước Java 5)
  2. Bật một giá trị id được chỉ định (như heneryville mô tả ) hoặc giá trị thứ tự của các giá trị enum; I EguideView.GUIDE_VIEW_SEVEN_DAY.ordinal()
  3. Xác định giá trị enum được đại diện bởi giá trị int và sau đó bật giá trị 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;
        }
    }

    Bạn có thể thấy hữu ích hơn / ít bị lỗi hơn khi viết một valueOftriển khai tùy chỉnh lấy các giá trị số nguyên của bạn làm đối số để giải quyết giá trị enum thích hợp và cho phép bạn tập trung kiểm tra giới hạn của mình.


Cảm ơn nhiều. Tôi đã mất một lúc để sửa nó thành mã của mình nhưng hiện tại nó đang hoạt động tốt với mã ví dụ bạn đã đăng. 6 năm với C # và 1 năm với Java - không mấy khi tôi gặp điều gì đó khiến tôi khó chịu. Rất nhiều điểm giống nhau nhưng đôi khi như thế này lại rất khác. Tôi sẽ không quên điều này một cách vội vàng. :-)
Squonk

2
Bạn cần các tên enum không đủ điều kiện trong câu lệnh trường hợp, do đó case GuideView.SEVEN_DAY:, nó sẽ xảy ra lỗi biên dịch case SEVEN_DAY:.
haridsv

Đó là tuyệt vời anh em !!
Neo

42

Nếu whichViewlà một đối tượng của GuideView Enum, sau đây sẽ hoạt động tốt. Xin lưu ý rằng không có định nghĩa cho hằng số sau case.

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

4
làm thế nào mà điều này thậm chí có thể ?!
Jes Chergui

12

Các enums không nên đủ tiêu chuẩn trong nhãn trường hợp như những gì bạn có NDroid.guideView.GUIDE_VIEW_SEVEN_DAY, thay vào đó bạn nên xóa tiêu chuẩn và sử dụngGUIDE_VIEW_SEVEN_DAY


Thích cái này. Đơn giản!
Ninja lười biếng

5

Tôi thích một vài cách sử dụng của Java enum:

  1. .name () cho phép bạn tìm nạp tên enum trong String.
  2. .ordinal () cho phép bạn nhận giá trị số nguyên, dựa trên 0.
  3. Bạn có thể đính kèm các tham số giá trị khác với mỗi enum.
  4. và tất nhiên, đã bật công tắc.

enum với các tham số giá trị:

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

chuyển ví dụ:

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

3

Điều này sẽ hoạt động theo cách mà bạn mô tả. lỗi gì bạn nhận được? Nếu bạn có thể dán mã của bạn sẽ hữu ích.

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

CHỈNH SỬA: Bạn có chắc chắn muốn xác định một enum tĩnh không? Điều đó nghe có vẻ không đúng với tôi. Một enum cũng giống như bất kỳ đối tượng nào khác. Nếu mã của bạn biên dịch và chạy nhưng cho kết quả không chính xác, đây có thể là lý do.


"Các kiểu enum lồng nhau là tĩnh hoàn toàn. Có thể khai báo rõ ràng kiểu enum lồng nhau là tĩnh." - JLS §8.9 .
trashgod

@trashgod, thực sự- nhưng tôi sẽ luôn sử dụng khai báo ngầm để tránh nhầm lẫn vì đó thực sự là IMO rõ ràng hơn. Một enum tĩnh toàn cục (mà tôi cho rằng đây là) có lẽ sai trong hầu hết các trường hợp.
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

Điều đó chỉ hoạt động nếu bạn không lấy dữ liệu của mình ra bên ngoài. Vì OP cho biết giá trị nào trả về giá trị 1, 2, 3 không phải là TYPE nên phương pháp của bạn sẽ không hoạt động nếu không có trường hợp chuyển đổi đảo ngược lấy 1, 2, 3 và trả về TYPE trước khi đi vào trường hợp chuyển đổi mà anh ấy đã liệt kê ..
WORMSS

2

Ví dụ về hàm liên kết ngắn:

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

Giống như @Dhanushka đã nói, bỏ qua vòng loại bên trong "switch" là chìa khóa.


1

Tôi đang làm nó giống như

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

Và sử dụng trong Báo cáo chuyển đổi

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

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

case Preparing:
case Playing:

    playPause.setBackgroundResource(R.drawable.selpause);
    break;    
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.