11

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

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()thishelper()

编辑:我发现了一些关于这个的讨论- 但没有真正的答案。我的同事认为这实际上this.helper()是一个编译器错误。实际上,对于较新的 Java 版本,它似乎不起作用(尽管super.helper()确实如此):“找不到符号 helper()”。(尽管发生了一些奇怪的事情:在尝试了不同的 Java 版本之后,我无法this.helper()再次使用它们中的任何一个进行编译......)

4

5 回答 5

8

该错误消息具有误导性,只需将helper其设为受保护即可。

protected void helper(){
    // can be called from subclasses (such as FOO) since it is not private
}
于 2009-02-28T15:52:31.497 回答
3

Java Puzzlers 一书中介绍了类似的内容。IIRC,外部类上下文总是在超类之前查看。在这种情况下会找到助手。但是我们在静态上下文中构造值(实际上有一个private static finalbefore FOO)。因此错误。

试试super.helper();

于 2009-02-24T12:13:15.130 回答
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 可以让您对父级进行私有访问。

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

于 2009-02-24T14:24:59.587 回答
1

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

一个合理的解决方案是将方法访问从私有更改为受保护,以提供对枚举常量“子类”的访问。

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

于 2009-05-21T03:56:11.157 回答
0

一篇文章提到了这个问题,不幸的是它是德文的。也许您仍然可以提取一些有用的信息。

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

于 2009-02-24T12:04:31.513 回答