枚举定义中的静态上下文

时间:2009-02-24 11:37:37

标签: java enums javac

Java enum工具提供的语法糖有时会有点混乱。考虑这个不编译的例子:

public enum TestEnum {

    FOO("foo") {
        public void foo() {
            helper();  // <- compiler error
        }
    };

    String name;
    TestEnum(String name) {
        this.name = name;
    }

    public abstract void foo();

    private void helper(){
        // do stuff (using this.name, so must not be static)
    }
}

任何人都可以解释为什么编译器会说

  

无法从静态上下文引用非静态方法'helper()'

这个背景究竟是如何静止的?

您可以通过更改对 this. helper()的调用来进行此编译(这里有一个令人困惑的地方:如果我们真的在“静态上下文”中,就像编译器一样建议,“this”如何工作?)或将helper()的可见性提高到默认级别。你更喜欢哪个?此外,随意提出一个更好的问题标题: - )

修改:我找到some discussion about this - 但没有真正的答案。我的同事认为this.helper()工作的事实实际上是一个编译器错误。事实上,对于较新的Java版本,似乎可以工作(尽管super.helper()确实如此):“找不到符号助手()”。 (虽然有一些奇怪的事情发生了:在尝试使用不同的Java版本后,我无法再使用this.helper()进行编译......)

5 个答案:

答案 0 :(得分:8)

错误消息具有误导性,只需使helper受到保护即可。

protected void helper(){
    // can be called from subclasses (such as FOO) since it is not private
}

答案 1 :(得分:3)

Java Puzzlers一书中介绍了类似的内容。 IIRC,在超类之前总是要考虑外部类的上下文。在这种情况下,找到帮助者。但我们正在静态上下文中构造值(在private static final之前有效FOO。因此错误。

尝试super.helper();

答案 2 :(得分:2)

如果我将你的枚举翻译成它的类结构,它看起来大致如下:

public abstract class TestEnum {

  public static final TestEnum FOO = new FOO("foo") {
    public void foo() {
        helper();  // <- compiler error
    }
 };

  String name;
  TestEnum(String name) {
      this.name = name;
  }

  public abstract void foo();

  private void helper(){
    // do stuff (using this.name, so must not be static)
  }

}

实例FOO是扩展TestEnum的任何类。这就是我相信你无法访问helper()的原因,因为它是私有的。所以this.helper()可能不应该工作。我不确定为什么即使super.helper()也能正常工作,但也许enum会让你私密访问父母。

至于静态上下文错误,我同意错误信息似乎没有意义。

答案 3 :(得分:1)

您可以将每个枚举常量视为枚举类的子类的唯一实例。就像“常规”类一样,枚举“子类”不能访问枚举“超类”的私有成员。 (我不能重新创建你提到的“这个”解决办法。)

合理的解决方案是将方法访问权限从 private 更改为 protected ,以便访问枚举常量“子类”。

更好的问题标题建议:“Java私有枚举方法?”或者只是“私有枚举方法”(让Java标记处理Java-ness)

答案 4 :(得分:0)

article提到这个问题,遗憾的是它是用德语写的。也许你仍然可以提取一些有用的信息。

编辑:似乎与你的问题有些不同。我仍然不明白你的例子的行为,我也在这里看到。