Java 调用enum';s法

Java 调用enum';s法,java,enums,Java,Enums,我有以下枚举: enum Days{ TODAY{ @Override public Date getLowerBound(){ another(); //1 currentUpperBound(); //2 return null; } @Override public Date another() {

我有以下枚举:

 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
编译得好吗?这两种方法都是非静态的。我看不出有什么问题。。。也许这和日食有关


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

我建议将
currentUpperBounds()
设置为受保护的而不是私有的。另一种解决方案是在您的通话前加上
super.
,这也适用于:

@Override
public Date getLowerBound(){
   another();
   super.currentUpperBound();
   return null;
}
@Override
public Date getLowerBound(){
   another();
   TODAY.currentUpperBound();
   return null;
}
或者,今天也可以:

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

Mick Mnemonic在这篇文章中提到了一个很好的答案,这很好地解释了这个问题。

您可以将
currentUpperBound
方法声明为
abstract
,并在您的实例中实现它,或者让它保持实现状态

在这两种情况下,都应该使用非privateaccess修饰符声明它

这里的编译器错误消息非常混乱。 它假定
currentUpperBound
应该是
static
,这将允许您从实例访问,即使该方法声明为
private

TL;博士 解决你的问题 我建议将
currentUpperBound()
方法
设置为protected

为什么?

您应该考虑< En强大>每个枚举值作为匿名代码子类<代码>天< /代码> <强>。此外,由于枚举必须保证其每个值都是唯一的(例如,您可以使用

=
测试相等性),它存储为
静态最终
字段
(因此也有使用大写字母命名枚举值的习惯)

理解幕后的枚举 代码等价 要显示有关枚举如何工作的一些代码,请执行以下操作1:

(几乎)相当于:

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
equals(Object)
在这里是完美的,因为它只测试这一点

-为什么可以从
MyEnum
继承方法,或者访问
private static
方法,但不能访问
private
非静态方法
  • 这些值存储为
    静态
    字段,因此它们无法访问实例上下文
  • 值inherit
    MyEnum
    ,因此任何可以通过legacy访问的内容都对他们可见
为什么我说这几乎是等价的? 枚举机制中嵌入了一些附加控件

例如,
开关
能够判断枚举的每个值是否有
大小写
:尝试只测试一些值,而不定义
默认值
,编译器将发出警告。如果只是使用带有常量的抽象类,这是不可能的

values()
方法还表明,与我的简单示例相比,情况更加复杂,但我认为这有助于理解



1根据我对

的理解,第二个不是抽象的。这意味着它必须是枚举上下文中的静态。私有方法不能重写make currentUpperBound()公开。错误消息很混乱。我理解问题所在,是的。我会让他们使用默认的访问修饰符。谢谢。我想知道为什么错误是完全不相关的。虽然将其更改为
protected
public
可以修复它。它是否由于某种原因与静态上下文相关。以及将方法更改为静态修复错误也是…:O@Codebender我也是,但我认为这一直都是eclipse。从技术上讲,将方法定义为静态方法也是可行的。似乎今天可以访问静态私有,但不能访问非静态私有。有趣的是,我们必须对此进行一些阅读。@FlorianSchaetz确实很有趣。为什么静态私有方法有效?但这是doesn没有提供静态私有的原因。JSL说,enum主体是一个匿名类,不是静态类。但可能与此有关。@FlorianSchaetz我在吃午餐时想到了它,认为我更了解它在幕后的工作原理。我修改了我的答案,并有兴趣选择你我想我发现了另一个有趣的细节:你实际上可以调用私有的非静态方法。你只需要使用
super.
。所以在你的例子中
super.unreactlemethod()
在重写的
sayMyName
方法中起作用。在整个事情变得容易之前…在它前面加上
MyEnum。
也起作用。有趣的是,但慢慢地我意识到我对Java的理解是多么零碎,尤其是在细节方面。有关更多细节,请参阅中的优秀答案。