【问题标题】:Java: using switch statement with enum under subclassJava:在子类下使用带有枚举的switch语句
【发布时间】:2012-04-27 00:46:29
【问题描述】:

首先我要声明的是,我对 C# 中的枚举更加熟悉,而 Java 中的枚举似乎是一团糟。

如您所见,我尝试在下一个示例中使用 switch 语句 @ enums,但无论我在做什么,我总是会收到错误。

我收到的错误是:

合格的案例标签SomeClass.AnotherClass.MyEnum.VALUE_A必须替换为不合格的枚举常量VALUE_A

问题是我非常理解错误,但我不能只写 VALUE_A,因为枚举位于另一个子类中。有没有办法解决这个问题?为什么会发生在 Java 中?

//Main Class
public class SomeClass {

    //Sub-Class
    public static class AnotherClass {
        public enum MyEnum {
            VALUE_A, VALUE_B
        }    
        public MyEnum myEnum;
    }

    public void someMethod() { 
        MyEnum enumExample //...

        switch (enumExample) {
            case AnotherClass.MyEnum.VALUE_A: { <-- error on this line
                //..
                break;
            }
        }
    }
}

【问题讨论】:

  • 正如 darrengorman 评论的那样,Java Enum 一旦你掌握了它们,就会非常方便地使用它们——一点也不乱。它们比在其他平台上看到的简单枚举(仅仅是一个标记的整数值)更加灵活和实用。请参阅Oracle Tutorial。发现优化的Set/Map 实现:EnumSet & EnumMap
  • 当您尝试限定案例陈述时;在某种程度上,您试图说我可以在单个 switch 语句中混合不同类型的枚举(不仅仅是相同的枚举类型)。 Java 已经用这种方法阻止了它,正如这里所讨论的 digizol.com/2010/10/enum-case-label-switch-java-qualified.html
  • 在 IntelliJ 2018.2 中重构(移动)一个类时发生在我身上

标签: java enums switch-statement


【解决方案1】:

Java 会自动推断 case 中元素的类型,因此标签必须是不合格的。

int i;
switch(i) {
   case 5: // <- integer is expected
}
MyEnum e;
switch (e) {
   case VALUE_A: // <- an element of the enumeration is expected
}

【讨论】:

  • 为什么必须不合格?
  • 如果你有资格,那么你可能会使用 MyEnum 以外的其他东西,这是没有意义的。
  • @Kru,但我可以对非枚举类型的 case 表达式使用一些语法上的东西。例如。 static final int MY_CONST = 7; …; switch(intVariable) {case MY_CONST: …;} 而不是 case 7。因此,对枚举的这种限制使 no 有意义(我不仅可以使用主要文字,还可以为整数 switch 表达式使用手动定义的常量,但我不能使用手动定义的常量,但只能枚举的主要名称)。
  • Java 中的@Sasha 枚举没有像 C++ 中那样分配整数。它们就像 java boolean 一样是抽象的。
  • @user13947194,没有人说他们有。我只是指出了一个逻辑谬误:对于一种类型,我们可以同时使用主要文字和手动定义的常量,而对于另一种类型,我们只能使用主要名称但不能使用手动定义的常量。
【解决方案2】:

改成这样:

switch (enumExample) {
    case VALUE_A: {
        //..
        break;
    }
}

线索在错误中。您无需使用枚举类型限定case 标签,只需使用它的值即可。

【讨论】:

  • 好吧,我觉得自己很愚蠢 :-( 你说得完全正确,我确信我尝试了这条确切的路线,但出现了错误,所以我转而确定案例,但你的建议确实有效。跨度>
  • 顺便说一句,我想你会发现,一旦你开始更多地使用它们,Java 中的枚举就非常有用,我不会说它们是一团糟:)
  • @milkplusvellocet,我知道这篇文章已经很老了,但我很好奇为什么 Java 不允许在 switch 语句中使用 qualified case label
  • @cRane01 不确定,但它使语法更清晰。在每种情况下指定类型将是完全多余的
  • @HelloGoodbye 不,switch语句的变量定义了case语句的类型,所以它只能是一个枚举。
【解决方案3】:

这样写someMethod()

public void someMethod() {

    SomeClass.AnotherClass.MyEnum enumExample = SomeClass.AnotherClass.MyEnum.VALUE_A;

    switch (enumExample) {
    case VALUE_A:
        break;
    }

}

在 switch 语句中你只能使用常量名。

【讨论】:

    【解决方案4】:

    应该这样做:

    //Main Class
    public class SomeClass {
    
        //Sub-Class
        public static class AnotherClass {
            public enum MyEnum {
                VALUE_A, VALUE_B
            }    
            public MyEnum myEnum;
        }
    
        public void someMethod() { 
            AnotherClass.MyEnum enumExample = AnotherClass.MyEnum.VALUE_A; //...
    
            switch (enumExample) {
                case VALUE_A: { //<-- error on this line
                //..
                break;
                }
            }
        }
    }
    

    【讨论】:

    • 你拯救了这一天!
    【解决方案5】:

    这就是我使用它的方式。而且效果非常好 -

    public enum Button {
            REPORT_ISSUES(0),
            CANCEL_ORDER(1),
            RETURN_ORDER(2);
    
            private int value;
    
            Button(int value) {
                this.value = value;
            }
    
            public int getValue() {
                return value;
            }
        }
    

    还有switch-case如下图

    @Override
    public void onClick(MyOrderDetailDelgate.Button button, int position) {
        switch (button) {
            case REPORT_ISSUES: {
                break;
            }
            case CANCEL_ORDER: {
                break;
            }
            case RETURN_ORDER: {
                break;
            }
        }
    }
    

    【讨论】:

      【解决方案6】:

      错误:

      case AnotherClass.MyEnum.VALUE_A
      

      对:

      case VALUE_A:
      

      【讨论】:

      • 我赞成你的,因为它更清楚问题是什么。
      【解决方案7】:

      Java 14 开始,可以使用 switch 表达式。

      为了这篇文章

      public enum MyEnum {
          VALUE_A, VALUE_B;
      }
      
      public void someMethod() { 
          MyEnum enumExample //...
      
          switch (enumExample) {
              case VALUE_A -> {
                  // logic
              }
              case VALUE_B -> {
                  // logic
              }   
          }
      }
      

      切换表达式

      与所有表达式一样,switch 表达式计算为单个值并且可以在语句中使用。它们可能包含“case L ->”标签,无需使用 break 语句来防止失败。您可以使用 yield 语句来指定 switch 表达式的值。

      public enum Month {
          JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC;
      }
      

      示例 1:返回值。

      public static int getNoOfDaysInAMonth(Month month, boolean isLeapYear) {
          return switch(month) {
              case APR, JUN, SEP, NOV -> 30;
              case FEB -> (isLeapYear)? 29: 28;
              case JAN, MAR, MAY, JUL, AUG, OCT, DEC -> 31;
          };
      }
      

      示例 2:不返回值。

      public static void printNoOfDaysInAMonth(Month month, boolean isLeapYear) {
          switch(month) {
              case APR, JUN, SEP, NOV -> {
                  System.out.println("30 days");
              }
              case FEB -> {
                  System.out.println(((isLeapYear)? 29: 28) + " days");
              }
              case JAN, MAR, MAY, JUL, AUG, OCT, DEC -> {
                  System.out.println("31 days");
              }
          };
      }
      

      参考

      Switch Expressions

      【讨论】:

        猜你喜欢
        • 2011-12-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-01-17
        相关资源
        最近更新 更多