Java将enum与switch语句一起使用


106

我已经看过类似于此问题的各种问答,但是还没有找到解决方案。

我所拥有的一个枚举代表了观看电视指南的不同方式...

在NDroid Application类中

static enum guideView {
    GUIDE_VIEW_SEVEN_DAY,
    GUIDE_VIEW_NOW_SHOWING,
    GUIDE_VIEW_ALL_TIMESLOTS
}

...当用户更改视图时,事件处理程序会收到int0-2的值,而我想做这样的事情...

在Android Activity onClick(DialogInterface dialog, int which)事件处理程序中

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

我习惯了C#枚举和select / case语句,这些语句将允许类似上面的内容,而且我知道Java会做一些不同的事情,但我只是不明白我需要做什么。

我将不得不诉诸if陈述吗?我可能只有3个选择,所以我可以这样做,但我想知道如何用Java中的切换用例来完成。

编辑抱歉,我没有完全扩展此问题,因为我将其视为通用Java问题。我已经添加了这个问题,以进一步解释。

没有什么是特定于Android的,这就是为什么我没有将其标记为Android,而是在Application类中定义了枚举,而我不希望在其中切换的代码位于的原因Activity。枚举是静态的,因为我需要从多个活动中访问它。


1
case GUIDE_VIEW_SEVEN_DAY在适当进口后才进行;您有什么问题?
戴夫·牛顿

您不能只让事件处理程序接收一个枚举吗?除此之外,也许这将有助于:stackoverflow.com/questions/5292790/...
布莱恩·罗奇

@Dave:抱歉,我已更正代码以显示其状态。Eclipse给我一个Type Mismatch错误,提示它无法从guideView转换为int。
Squonk

@Brian:这是一个Android应用,事件处理程序(OnClickListener )由DialogInterface我必须实现的接口定义。
Squonk

@MisterSquonk哦,我想念您是从int那里得到的-对不起,请参阅Ophidian的回答,尽管我将功能放在枚举中。
戴夫·牛顿

Answers:


162

您缺少的部分是从整数转换为类型安全的枚举。Java不会自动执行此操作。有两种方法可以解决此问题:

  1. 使用静态最终整数列表而不是类型安全的枚举,然后打开接收到的整数值(这是Java 5之前的方法)
  2. 开启指定的id值(如heneryville所述)或枚举值的序数值;即guideView.GUIDE_VIEW_SEVEN_DAY.ordinal()
  3. 确定由int值表示的枚举值,然后打开该枚举值。

    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实现(以整数值作为参数来解析适当的枚举值并允许您集中边界检查)的自定义实现更有用/更少出错。


非常感谢。我花了一些时间将其纳入我的代码,但现在与您发布的示例代码一起正常工作。使用C#的6年和使用Java的1年-我很少遇到让我感到困惑的事情。如此众多的相似之处,但偶尔的相似之处却是如此。我不会急于忘记这一个人。:-)
Squonk

2
您需要在case语句中使用非限定的枚举名称,因此case GuideView.SEVEN_DAY:会出现编译错误,应该为case SEVEN_DAY:
haridsv 2014年

棒极了!
Neo

42

如果whichView是GuideView枚举的对象,则可以很好地进行以下操作。请注意,之后的常数没有限定符case

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

4
这怎么可能?
Jes Chergui 2014年

12

枚举不应像您所拥有的那样在格标签内进行限定NDroid.guideView.GUIDE_VIEW_SEVEN_DAY,而应删除限定并使用GUIDE_VIEW_SEVEN_DAY


更喜欢这个。简单!
懒惰的忍者

5

我喜欢Java枚举的一些用法:

  1. .name()允许您获取String中的枚举名称。
  2. .ordinal()允许您获取基于0的整数值。
  3. 您可以在每个枚举中附加其他值参数。
  4. 并且当然启用了开关

具有值参数的枚举:

    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

编辑:您确定要定义一个静态枚举吗?对我来说这听起来不对。枚举与任何其他对象非常相似。如果您的代码可以编译并运行,但给出的结果不正确,则可能是原因。


“嵌套的枚举类型是隐式静态的。允许显式声明嵌套的枚举类型为静态。” — JLS 8.9节
2011年

的确是@trashgod,但是我总是使用隐式声明来避免混淆,因为这实际上是更明显的IMO。在大多数情况下,全局静态枚举(这就是我所假设的)可能是错误的。
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不是一个类型的方法将不认为需要1,2,3,并再进他列出的开关的情况下返回类型..相反的开关情况下不工作
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所说,省略“ switch”内的限定词是关键。


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语句中使用

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

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

case Preparing:
case Playing:

    playPause.setBackgroundResource(R.drawable.selpause);
    break;    
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.