调用enum的方法

时间:2015-08-11 08:29:34

标签: java enums

我有以下枚举:

 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

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

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

3 个答案:

答案 0 :(得分:9)

我建议currentUpperBounds() 保护而不是私有。另一个解决方案是使用super.为您的呼叫添加前缀,这也适用于:

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

或者,TODAY也有效:

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

Mick Mnemonic在这个duplicate中提到了很好的答案,这很好地解释了它。

答案 1 :(得分:4)

TL; DR

解决您的问题

我建议使用currentUpperBound()方法protected

为什么?

您应该将枚举的每个值视为Days 的匿名子类。此外,由于枚举必须保证其每个值都是唯一的(例如,您可以测试与==的相等),它将存储为static final字段(因此还有用大写字母命名枚举值的习惯。

了解场景背后的枚举

代码等效

显示关于枚举如何工作的一些代码 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
    }
}

当你以这种方式写作时,有些事情变得更容易理解:

- 为什么==用于测试枚举等式

每个值只有一个指针。 Object' s equals(Object)在这里非常完美,因为它仅测试它。

- 为什么你可以从MyEnum继承方法或访问private static方法,而不是private非静态方法

  • 这些值存储为static字段,因此无法访问实例上下文。
  • 该值继承MyEnum,因此可以通过遗产访问任何内容。

为什么我说几乎等同?

枚举机制中嵌入了一些额外的控件。

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

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

1 基于我对JSL 的理解

答案 2 :(得分:3)

您可以将currentUpperBound方法声明为abstract并在您的实例中实施,也可以将其保留。

在这两种情况下,您都应使用非private访问修饰符声明它。

这里的编译器错误消息非常混乱。 它假设currentUpperBound应为static,即使该方法声明为private,也会授予您对实例的访问权限。