Java枚举和切换语句 - 默认情况?

Kit*_*YMG 56 java enums

对于建议抛出异常的人:
抛出异常不会给我一个编译时错误,它会给我一个运行时错误.我知道我可以抛出一个异常,我宁愿在编译期间死也不会在运行时死掉.

首先,我使用的是eclipse 3.4.

我有一个数据模型,其模式属性是枚举.

enum Mode {on(...), off(...), standby(...); ...}
Run Code Online (Sandbox Code Playgroud)

我目前正在写这个模型的视图,我有代码

...
switch(model.getMode()) {
case on:
   return getOnColor();
case off:
   return getOffColor();
case standby:
   return getStandbyColor();
}
...
Run Code Online (Sandbox Code Playgroud)

我收到错误"此方法必须返回类型java.awt.Color的结果",因为我没有默认情况,并且在函数末尾没有返回xxx. 在有人为枚举添加另一种类型的情况下出现编译错误(例如关闭)所以我不想放置抛出AssertionError的默认情况,因为这将使用修改后的模式进行编译而不会被视为错误直到运行时.

我的问题是:
为什么EclipseBuilder(和javac)没有意识到这个开关涵盖了所有可能性(或者它是否涵盖了它们?)并且停止警告我需要返回类型.有没有办法,我可以做我想要的,而无需向Mode添加方法?

如果失败了,是否有一个选项可以在不包含所有Enum可能值的switch语句上发出警告/错误?

编辑:Rob:这是一个编译错误.我只是尝试用javac编译它,我得到一个"缺少返回语句"错误,目标是方法的最后一个}.Eclispe只是将错误放在方法的顶部.

mtp*_*typ 71

您始终可以使用Enum with Visitor模式:

enum Mode {
  on {
      public <E> E accept( ModeVisitor<E> visitor ) {
         return visitor.visitOn();
      }
  },
  off {
      public <E> E accept( ModeVisitor<E> visitor ) {
         return visitor.visitOff();
      }
  },
  standby {
      public <E> E accept( ModeVisitor<E> visitor ) {
         return visitor.visitStandby();
      }
  }

  public abstract <E> E accept( ModeVisitor<E> visitor );

  public interface ModeVisitor<E> {
      E visitOn();
      E visitOff();
      E visitStandby();
  }
}
Run Code Online (Sandbox Code Playgroud)

然后你将实现类似以下内容:

public final class ModeColorVisitor implements ModeVisitor<Color> {
    public Color visitOn() {
       return getOnColor();
    }

    public Color visitOff() {
       return getOffColor();
    }

    public Color visitStandby() {
       return getStandbyColor();
    }

}
Run Code Online (Sandbox Code Playgroud)

您可以按如下方式使用它:

return model.getMode().accept( new ModeColorVisitor() );
Run Code Online (Sandbox Code Playgroud)

这更详细,但如果声明了新的枚举,你会立即得到编译错误.

  • 这是因为它做了我需要/想要的东西.它允许基于枚举状态的任意逻辑,不要求枚举跟踪对其无意义的事物进行跟踪. (2认同)

ega*_*aga 57

您必须在Eclipse(窗口 - >首选项)设置中启用"错误级别未包含在交换机中的枚举类型常量".

在方法结束时抛出异常,但不要使用默认情况.

public String method(Foo foo)
  switch(foo) {
  case x: return "x";
  case y: return "y";
  }

  throw new IllegalArgumentException();
}
Run Code Online (Sandbox Code Playgroud)

现在,如果有人稍后添加新案例,Eclipse会让他知道他错过了一个案例.所以除非你有充分的理由这样做,否则不要使用默认值.

  • 我想让你知道我接受了另一个答案而不是你的答案.你的工作很棒...只要每个人都使用Eclispe设置选项.我选择的答案适用于所有java编译器.如果我能再次评价你,我愿意. (7认同)

ama*_*ion 10

我不知道你为什么会得到这个错误,但这里有一个建议,你为什么不定义枚举本身的颜色?然后你不会忘记定义一个新的颜色.

例如:

import java.awt.Color;

public class Test {

    enum Mode 
    {
        on (Color.BLACK), 
        off (Color.RED),
        standby (Color.GREEN);

        private final Color color; 
        Mode (Color aColor) { color = aColor; }
        Color getColor() { return color; }
    }

    class Model
    {
        private Mode mode;
        public Mode getMode () { return mode; }
    }

    private Model model;

    public Color getColor()
    {
        return model.getMode().getColor();
    }   
}
Run Code Online (Sandbox Code Playgroud)

顺便说一句,这里的比较是原始情况,编译错误.

import java.awt.Color;
public class Test {

    enum Mode {on, off, standby;}

    class Model
    {
        private Mode mode;
        public Mode getMode () { return mode; }
    }

    private Model model;

    public Color getColor()
    {
        switch(model.getMode()) {
        case on:
           return Color.BLACK;
        case off:
           return Color.RED;
        case standby:
           return Color.GREEN;
        }
    }   
}
Run Code Online (Sandbox Code Playgroud)


Pau*_*ier 6

我想这可能是因为model.GetMode()可能返回null.

  • 这没有意义.无论如何,这将导致NullPointerException.你不能定义"case null" (5认同)
  • 对.枚举是拒绝类型. (2认同)
  • 我刚刚检查过 我曾经认为Sun知道wtf他们正在使用Enums,但显然你可以为枚举类型指定null.那个脑死亡的想法是那样的.感谢您指出了这一点. (2认同)
  • 虽然枚举变量可以为空,但是这些空值不能在开关中使用(它们会导致NullPointerException).这当然不是原因. (2认同)