Java使用枚举和switch语句

125

我看过SO中类似于这个问题的各种问答,但没有找到解决方案。

我有一个枚举类型,表示不同的电视指南视图方式...

在NDroid的Application类中

static enum guideView {
    GUIDE_VIEW_SEVEN_DAY,
    GUIDE_VIEW_NOW_SHOWING,
    GUIDE_VIEW_ALL_TIMESLOTS
}

当用户更改视图时,事件处理程序会接收一个从0-2的int,我想做类似于这样的事情...

在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#的枚举和选择/情况语句,这使得上述内容成为可能。我知道Java的处理方式与此不同,但我无法理解我需要做什么。

我是否必须使用if语句?可能只有3种选择,所以我可以这样做,但我想知道如何在Java中使用switch-case语句来完成。

编辑 对不起,我没有完全阐述问题,因为我认为这是一个通用的Java问题。我已经补充了问题以进一步解释。

这里没有任何特定于Android的内容,这就是为什么我没有将其标记为Android的原因,但是枚举在Application类中定义,而我想要使用switch的代码则在一个Activity中。该枚举是静态的,因为我需要从多个活动访问它。


1
在正确导入后应该只有 case GUIDE_VIEW_SEVEN_DAY,你遇到了什么问题? - Dave Newton
你不能只是让你的事件处理程序接收一个枚举吗?除此之外,也许这个链接可以帮到你:https://dev59.com/cG435IYBdhLWcg3wpx2x - Brian Roach
@Dave:哎呀,抱歉,我已经修正了代码以显示其正确形式。Eclipse 给了我一个类型不匹配的错误,说它无法将 guideView 转换为 int 类型。 - Squonk
@Brian:这是一个Android应用程序,事件处理程序(OnClickListener)由我必须实现的DialogInterface接口定义。 - Squonk
@MisterSquonk 哦,我错过了你从int获取它的事实 - 抱歉,请查看Ophidian的答案,虽然我会将功能放在枚举中。 - Dave Newton
你可以使用枚举类型的枚举值或整数来进行开关操作(哈哈,显而易见)。你需要先获取一个枚举类型的变量 GuideView e = GuideView.valueOf(i) 或获取所有枚举的整数值(后者的缺点是你不能保证没有未声明的值,应该添加一个默认情况:case)。 - eckes
8个回答

184

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

  1. Use a list of static final ints rather than a type-safe enum and switch on the int value you receive (this is the pre-Java 5 approach)
  2. Switch on either a specified id value (as described by heneryville) or the ordinal value of the enum values; i.e. guideView.GUIDE_VIEW_SEVEN_DAY.ordinal()
  3. Determine the enum value represented by the int value and then switch on the enum value.

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

    You may find it more helpful / less error prone to write a custom valueOf implementation that takes your integer values as an argument to resolve the appropriate enum value and lets you centralize your bounds checking.


非常感谢。我花了一些时间将它整合到我的代码中,但现在它已经很好地运行了,与您发布的示例代码相结合。使用C#已有6年,Java已有1年 - 我很少遇到让我困惑的问题。虽然两者有很多相似之处,但偶尔也会出现像这样截然不同的情况。我不会忘记这个问题的。 :-) - Squonk
2
在 case 语句中,您需要使用未经限定的枚举名称,因此 case GuideView.SEVEN_DAY: 会导致编译错误,应该改为 case SEVEN_DAY: - haridsv

49

如果 whichView 是 GuideView 枚举的一个对象,以下代码可以正常工作。请注意,在 case 后面没有常量的限定符。

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

16

在 case 标签内,枚举(enums)不应该被限定其范围,就像你的代码中使用了 NDroid.guideView.GUIDE_VIEW_SEVEN_DAY,相反地,你应该取消限定并使用 GUIDE_VIEW_SEVEN_DAY


5

我喜欢 Java 枚举的几种用法:

  1. .name() 允许你以 String 形式获取枚举名称。
  2. .ordinal() 允许你获取基于 0 的整数值。
  3. 你可以给每个枚举附加其他值参数。
  4. 当然,支持 switch 语句。

带有值参数的枚举:

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

switch示例:

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

3

简短的关联函数示例:

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"内部的限定符是关键。


3
这应该按照您的描述方式工作。您遇到什么错误?如果您可以将您的代码粘贴到pastebin中,那会很有帮助。 http://download.oracle.com/javase/tutorial/java/javaOO/enum.html 编辑:您确定要定义一个静态枚举吗?对我来说听起来不太对。枚举与任何其他对象非常相似。如果您的代码编译并运行但给出了错误的结果,则可能是这个原因。

嵌套枚举类型是隐式静态的。可以明确声明嵌套枚举类型为静态。——JLS §8.9 - trashgod
@trashgod,确实如此 - 但我总是使用隐式声明来避免混淆,因为在我看来这更明显。一个全局静态枚举(我认为这就是)在大多数情况下可能是错误的。 - 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

只有在您不从外部获取数据时才有效。由于原帖中返回值为1、2、3而不是类型,因此您的方法将无法正常工作,除非倒转switch语句并在进入列出的switch语句之前使用一个接受1、2、3并返回类型的函数。 - WORMSS

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接