【问题标题】:Why do we allow referring to an enum member of an enum member in Java?为什么我们允许在 Java 中引用枚举成员的枚举成员?
【发布时间】:2018-11-05 20:26:24
【问题描述】:

给定以下枚举:

enum Repeat {
    Daily,
    Weekly,
    Yearly
}

我意识到我们可以这样写:

Repeat repeat = Repeat.Daily.Weekly.Yearly.Weekly;

相当于:

Repeat repeat = Repeat.Weekly;

我可以知道为什么允许这样的语法吗?有没有办法让编译器警告我们不要这样做?

【问题讨论】:

标签: java enums


【解决方案1】:

有没有办法让编译器警告我们?

是的,使用好的 IDE 并打开警告。这样一来,您将在编写代码时立即收到通知,甚至在您编译之前。

例如在Eclipse中称为“对静态成员的非静态访问”:

【讨论】:

    【解决方案2】:

    这是允许的,因为Daily, Weekly, Yearlydefaultenum 内的static 字段,并包含Repeat 的对象。此外,您将收到来自编译器"The static field Repeat.Weekly should be accessed in a static way" 的警告。它类似于下面的代码行。

    class Foo{
        public static Foo obj1 = new Foo();
        public static Foo obj2 = new Foo();
        public static Foo obj3 = new Foo();
    }
    
    Foo f = Foo.obj1.obj2.obj3; // will work fine but you will get a warning from the compiler.
    

    这是Repeat 枚举字节码检查的一部分,从这里可以清楚地看出Enum 变量是static 并持有枚举本身的对象。

       0: new           #1                  // class com/java8/demo/Repeat
       3: dup
       4: ldc           #14                 // String Daily
       6: iconst_0
       7: invokespecial #15                 // Method "<init>":(Ljava/lang/String;I)V
      10: putstatic     #19                 // Field Daily:Lcom/java8/demo/Repeat;
      13: new           #1                  // class com/java8/demo/Repeat 
    

    【讨论】:

      【解决方案3】:

      枚举实例只是枚举类的static 实例。

      我们有两种方法可以访问一个类的静态字段:

      1. 通过类本身:Repeat.Daily
      2. 通过类实例:Repeat.Daily.Daily

      当你链接你的枚举时:

      Repeat repeat = Repeat.Daily.Weekly.Yearly.Weekly;
      

      这就像从一个类的实例中获取一个静态字段。

      【讨论】:

        【解决方案4】:

        枚举字面量是静态成员,对于每个静态成员,都可以使用类引用来访问它们:

        TypeName.staticMember
        TypeName.staticMethod()
        

        或者在一个实例上:

        new TypeName().staticMember
        new TypeName().staticMethod()
        

        不鼓励使用第二种方法(编译器会发出警告)

        由于枚举文字只是静态成员,Repeat.Daily.Weekly.Yearly.Weekly 就像上面的第二个代码 sn-p,访问实例引用上的静态成员。

        有了一个类,那就是:

        class Type {
            static Type INSTANCE1, INSTANCE2, INSTANCE3;
        }
        

        并且可以使用Type.INSTANCE1.INSTANCE2.INSTANCE3 获得对INSTANCE3 的引用。这是有效的,但这是不好的做法。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-06-29
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-09-26
          • 2010-12-17
          相关资源
          最近更新 更多