【问题标题】:Strange behavior with Java enumsJava 枚举的奇怪行为
【发布时间】:2017-03-28 13:52:27
【问题描述】:

我在使用 java Enums 时遇到了奇怪的行为。如果你写下一个枚举:

public enum Test {
   public static final int C1 = 5;
}

你得到一个编译错误,这是预期的,因为你一开始没有声明枚举常量。

但奇怪的是,如果你只是在开头添加一个没有常量名的分号:

public enum Test {
   ;
   public static final int C1 = 5;
}

您的代码将被成功编译。

也许我的问题很愚蠢,java规范中有答案,但我还没有找到答案。

如果有人理解 java 编译器为什么这样做,请解释一下。

【问题讨论】:

标签: java enums


【解决方案1】:

意味着您正在创建一个空的 enum 。默认情况下,枚举应该有很少的枚举值。所以这里的分号被视为空 enum 。创建这样的枚举是一种不好的做法

【讨论】:

    【解决方案2】:

    正如另一个答案所指出的,JLS 的相关部分是 8.9,特别是 8.9.1,其中指出:

    枚举声明的主体可能包含枚举常量。枚举常量定义了枚举类型的一个实例。

    EnumBody:
    { [EnumConstantList] [,] [EnumBodyDeclarations] }

    要了解EnumBody 定义的含义,必须查看JLS Chapter 2.4, Grammar Notation,它说

    产生式右边的语法 {x} 表示零或 x 的出现次数更多。

    还有

    产生式右边的语法 [x] 表示零或 x 出现一次。也就是说,x 是可选符号。这 包含可选符号的替代实际上定义了两个 替代品:一种省略可选符号,另一种包括 它。

    这与您的问题有何关系?这意味着有效的枚举声明如下(以下是一些语法符号,请耐心等待):

    public enum Test {
    }
    
    public enum Test {
      [EnumConstantList]
    }
    
    public enum Test {
      [EnumConstantList] ,
    }
    
    public enum Test {
     ,
    }
    
    public enum Test {
      [EnumBodyDeclarations]
    }
    
    public enum Test {
     , [EnumBodyDeclarations]
    }
    
    public enum Test {
      [EnumConstantList] [EnumBodyDeclarations]
    }
    
    public enum Test {
      [EnumConstantList] , [EnumBodyDeclarations]
    }
    

    [EnumConstantList] 并不那么有趣,因为这是人们所期望的:

    EnumConstant {, EnumConstant}

    也就是说,一个或多个EnumConstant,用逗号分隔(我不会深入EnumConstant的定义,我已经陷入了一个足够深的兔子洞,而且它与问题无关)。

    [EnumBodyDeclarations] 的定义让事情变得有趣(终于):

    EnumBodyDeclarations:
    ; {ClassBodyDeclaration}

    这就是您的第一个示例无效的原因

    您错误地指定了EnumBodyDeclarations,如上面的摘录所示,它是一个非可选分号,后跟零个或多个ClassBodyDeclaration

    这就是您的第二个示例有效的原因

    它包含非可选分号,后跟有效的ClassBodyDeclaration

    呼。

    这也意味着以下是有效的枚举声明:

    public enum Test {
     ;
    }
    
    public enum Test {
     ,;
    }
    
    public enum Test {
       ,;
       public static final int C1 = 5;
    }
    
    public enum Test {
       CAT,
    }
    
    public enum Test {
       CAT;
    }
    
    public enum Test {
       CAT,;
    }
    
    public enum Test {
       CAT,;
       public static final int C1 = 5;
    }
    
    public enum Test {
       CAT;
       public static final int C1 = 5;
    }
    

    但从来没有

    public enum Test {
       CAT,
       public static final int C1 = 5;
    }
    

    【讨论】:

    • 感谢您写出如此全面的答案!你测试这些枚举声明吗?第二个和第三个没有编译。因此枚举主体的正确声明应该是:{ [EnumConstantList [,]] [EnumBodyDeclarations] }
    • 我对它们都进行了测试,它们都使用 Java 8 编译,包括第二个和第三个示例。您使用的是什么版本的 Java,编译器的抱怨是什么?
    • 对不起,我用 maven 构建了我的项目,但我没有注意到在验证阶段构建失败而不是编译。这是因为我在 pom 中添加了 checkstyle 插件。
    【解决方案3】:

    Java 枚举可以具有字段和方法以及常规枚举值:

    enum Color {
      RED,
      GREEN,
      BLUE;
    
      public static final int C1 = 5;
    }
    

    将分号放在那里只是一个没有任何值的枚举。相当无用,但可能。

    【讨论】:

      【解决方案4】:

      枚举主体必须包含枚举常量,以及可选其他类组件(方法等)。

      Java Language Spec section 8.9

      您的第一个示例没有声明任何常量和一个公共的 final 静态字段。您的第二个示例首先包含一个 empty 常量列表(并且违反直觉有效)

      您可以举第二个例子并添加一个枚举常量,例如

      public enum Test {
         INSERTED_ENUM;
         public static final int C1 = 5;
      }
      

      进一步证明这一点。

      【讨论】:

        猜你喜欢
        • 2012-11-15
        • 2017-07-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多