Java枚举益智游戏

假设我们有以下代码:
enum Case {
   CASE_ONE,
   CASE_TWO,
   CASE_THREE;
   private static final int counter;
   private int valueDependsOnCounter;
   static {
     int sum = 0;
     for(int i = 0; i<10; i++) {
       sum +=i;
     }
     counter = sum;
   } 
   Case() {
     this.valueDependsOnCounter = counter*counter;
   }
 }

您认为编译和运行代码的结果是什么?

  1. 编译器错误
  2. 运行时错误
  3. 运行正常,但valueDependsOnCounter具有奇怪的值
  4. 没关系

稍加思考。 (扰流块)答案是按以下顺序的第8个字母:bdcadcbabcad。
为了阐明这一点,有必要检查以下内容:
A.类中静态初始化的顺序:

  1. 静态viaribales出现的顺序
  2. 静态块出现的顺序
  3. 实例变量的出现顺序
  4. 构造函数

B.构造函数调用的顺序(这也适用于静态变量):

  1. 超级班
  2. 本地班

C.用Java表示枚举对象的方式:

1)名称E的枚举除其他外具有一个隐式静态最终字段,该枚举对每个枚举成员都具有类型E的n。 更具体地说,Caseclass可以通过以下方式编写:

enum Case {
 

     public static final Case CASE_ONE;
 

     public static final Case CASE_TWO;
 

     public static final Case CASE_THREE;
     

     …
 

     }

2)上面的成员按照声明的顺序出现,并且位于枚举的所有其他静态成员之上(这意味着它们是第一个要初始化的成员)。
3)枚举常量被认为是在相应字段初始化时创建的。

因此,编译器会发出类似“从枚举或实例初始化程序访问静态成员计数器是非法的”之类的错误。 这是因为枚举被初始化的顺序:
1)公共静态最终案例CASE_ONE;
2)公共静态最终案例CASE_TWO; 3)公共静态最终案例CASE_THREE; 4)公共静态最终计数器; 5)

static {
       ..
     counter = something;

     }

6)

Case() {
       this.valueDependsOnCounter = counter*counter;
     }

需要做的第一件事是初始化CASE_ONE,但是必须调用Case()构造函数,该构造函数又取决于仅在静态{}块中初始化(但尚未执行)的计数器。 。 现在,从构造函数访问静态变量将是一个巨大的限制,但这正是这种流程所暗示的,即您不能在枚举的构造函数中使用静态变量。 幸运的是,这不太正确。 该错误实际上试图告诉我们的是:“从构造函数,实例初始值设定项块或实例变量初始值设定项表达式中引用一个不是* compile-time constant *的枚举类型的静态字段是一个编译时错误。这种类型的。”。 实际上,编译器确实允许访问枚举构造函数中的statics字段,但仅适用于可以静态计算(作为优化机制)的那些字段。 如果我们有:

enum Case {
 
   CASE_ONE,
 
   CASE_TWO,
 
   CASE_THREE;

   private static final int counter = 0;
 
   private int valueDependsOnCounter;  
 
   Case() {
     this.valueDependsOnCounter = counter*counter;
   }
 
 }

,一切都会很好,因为编译器可以预测计数器的初始化,可以在构造函数中使用它,构建枚举实例,并将其分配给静态最终CASE_ONE变量。 但是由于计数器取决于一些难以预测的计算,因此会引起错误。

为了使代码仍然有效,有两种解决方案:

1)将所需的静态变量放在嵌套类中,然后从那里访问它们:

class Nested {
 
   private static final int counter;

   static {
 
     int sum = 0;

     for(int i = 0; i<10; i++) {
 
       sum +=i;


     }
 
     counter = sum;
 

   }

  }
 
 enum Case {
 
   CASE_ONE,
 
   CASE_TWO,
 
   CASE_THREE;
 

   private static final int counter; 

   private int valueDependsOnCounter;    
 
   Case() {
 

     this.valueDependsOnCounter = Nested.counter*Nested.counter;
 
   }

 }

2)在构造函数中而不是在静态块中初始化(推荐):

enum Case {

   CASE_ONE, 

   CASE_TWO,

   CASE_THREE; 

   private static final int counter;
 
   private int valueDependsOnCounter;    
 
   static {
 
     int sum = 0;
 
     for(int i = 0; i<10; i++) {
 
       sum +=i;

     }

     counter = sum;
 
     for(Case c : Case.values()) {
 
       c.valueDependsOnCounter = counter*counter;
 
     }
 
   }
 
 }

讨论的异常甚至在JAVA规范文档中指定。

参考: Transylvania JUG博客上的JCG合作伙伴 Attila-Mihaly Balazs的枚举谜题


翻译自: https://www.javacodegeeks.com/2012/04/java-enum-puzzler.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值