调用枚举的方法TL;DR了解幕后的枚举

2022-09-04 20:36:59

我有以下枚举:

 enum Days{
    TODAY{
        @Override
        public Date getLowerBound(){
            another();             //1
            currentUpperBound();   //2
            return null;
        }

        @Override
        public Date another() {
            return null;
        }
    };

    public abstract Date getLowerBound();

    public abstract Date another();

    private Date currentUpperBound(){
        return null;
    }
}

为什么会导致编译时错误//2

Cannot make a static reference to the non-static method 
currentUpperBound() from the type Days

但是编译好吗?这两种方法都是非静态的。我看不出任何问题...也许它与Eclipse有关?//1

更新:正如@Florian Schaetz在评论中注意到的那样,如果我们声明具有修饰符的方法,它将正常工作。为什么?static private


答案 1

我建议将受保护而不是私有。另一种解决方案是在调用前面加上 前缀,这也有效:currentUpperBounds()super.

@Override
public Date getLowerBound(){
   another();
   super.currentUpperBound();
   return null;
}

或者,TODAY也适用于:

@Override
public Date getLowerBound(){
   another();
   TODAY.currentUpperBound();
   return null;
}

Mick Mnemonic在这个副本中提到了出色的答案,这很好地解释了这一点。


答案 2

TL;DR

问题的解决方案

我建议制作方法。currentUpperBound()protected

为什么?

应将枚举的每个值视为 Days 的匿名子类。此外,由于枚举必须保证其每个值都是唯一的(以便您可以测试相等性),因此它被存储为静态最终字段(因此也习惯于用大写字母命名枚举值。==

了解幕后的枚举

代码等效性

要显示一些关于枚举如何工作的代码1:

public enum MyEnum {
    JESSE {
       @Override
       public void sayMyName() {
           System.out.println("Pinkman");
       }
    }, WALTER;

    public void sayMyName() {
        System.out.println("Heisenberg");
    }

    private void unreachableMethod() {
        // try again
    }
}

(几乎)等效于:

public class MyEnum {
    private static final MyEnum JESSE = new MyEnum() {
       @Override
       public void sayMyName() {
           System.out.println("Pinkman");
       }
    };
    private static final MyEnum WALTER = new MyEnum();

    public void sayMyName() {
        System.out.println("Heisenberg");
    }

    private void unreachableMethod() {
        // try again
    }
}

当你以这种方式编写它时,有些东西变得更容易理解:

- 为什么适用于测试枚举相等性==

每个值只有一个指针。在这里是完美的,因为它只测试了这一点。Objectequals(Object)

- 为什么你可以从方法继承或访问方法,但不能从非静态方法继承或访问MyEnumprivate staticprivate

  • 这些值存储为字段,因此它们无法访问实例上下文。static
  • 该值继承,因此通过旧版可访问的任何内容对它们都是可见的。MyEnum

为什么我说这几乎是等价的?

枚举机制中嵌入了一些其他控件。

例如,能够判断枚举的每个值是否都有 a:尝试只测试一些值而不定义 ,编译器将引发警告。如果您只是使用带有常量的抽象类,这将是不可能的。switchcasedefault

该方法还表明,事情比我的简单例子更进化,但我认为这有助于理解。values()


1 基于我对JSL的理解