当开关用于枚举时,默认值的用法是什么?

2022-08-31 16:00:40

假设我有一个包含 2 个可能值的枚举:和 :ColorREDBLUE

public enum Color {
    RED,
    BLUE
}

现在假设我有一个用于此枚举的 switch 语句,其中我有两个可能值的代码:

Color color = getColor(); // a method which returns a value of enum "Color"
switch (color) {
case RED:
   ...
   break;

case BLUE:
   ...
   break;

default:
   break;
}

由于我有枚举的两个可能值的代码块,那么在上面的代码中有什么用法?default

如果代码以某种方式到达这样的块,我是否应该抛出一个异常?default

Color color = getColor(); // a method which returns a value of enum "Color"
switch (color) {
case RED:
   ...
   break;

case BLUE:
   ...
   break;

default:
   throw new IllegalArgumentException("This should not have happened");
}

答案 1

最好抛出异常,如第二个示例所示。您可以通过快速失败来提高代码的可维护性。

在这种情况下,这意味着如果您稍后(也许几年后)添加枚举值并且它到达switch语句,您将立即发现错误。

如果未设置默认值,则即使使用新的枚举值,代码也可能运行,并且可能具有不需要的行为。


答案 2

其他答案是正确的,说你应该实现一个引发异常的分支,以防将来向你的枚举添加新值。但是,我会更进一步,质疑为什么你首先要使用语句。defaultswitch

与C++和C#等语言不同,Java将Enum值表示为实际对象,这意味着您可以利用面向对象的编程。假设您的方法的目的是为每种颜色提供一个 RGB 值:

switch (color)
    case RED:
       return "#ff0000";
    ...

好吧,可以说,如果您希望每种颜色都有一个RGB值,则应将其作为其描述的一部分:

public enum Color
{
    RED("#FF0000"),
    BLUE("#0000FF");

    String rgb;
    public Color(String rgb) {
        this.rgb = rgb;
    }
    public getRgb() { return this.rgb; }
}

这样,如果以后添加新颜色,则几乎被迫提供 RGB 值。它甚至比其他方法更快速,因为您将在编译时而不是运行时失败。

请注意,如果需要,您可以执行更复杂的操作,包括让每种颜色提供其自己的抽象方法的自定义实现。Java中的枚举非常强大且面向对象,在大多数情况下,我发现我可以避免首先需要使用它们。switch