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()
到默认级别。你更喜欢哪个?另外,随意提出更好的问题标题:-)
编辑: 我发现 关于此的一些讨论 - 但没有真正的答案。我的同事认为这个事实 this.helper()
works实际上是一个编译器bug。事实上,似乎有更新的Java版本 不 工作(虽然 super.helper()
确实):“找不到符号助手()”。 (虽然有一些奇怪的事情发生了:尝试使用不同的Java版本后我无法获得 this.helper()
用它们中的任何一个再次编译...)
错误消息具有误导性,只是make helper
受保护,它会工作。
protected void helper(){
// can be called from subclasses (such as FOO) since it is not private
}
Java Puzzlers一书中介绍了类似的内容。 IIRC,在超类之前总是会考虑外部类的上下文。在这种情况下,找到帮助者。但我们正在静态环境中构建价值(实际上是一个 private static final
之前 FOO
)。因此错误。
尝试 super.helper();
。
错误消息具有误导性,只是make helper
受保护,它会工作。
protected void helper(){
// can be called from subclasses (such as FOO) since it is not private
}
Java Puzzlers一书中介绍了类似的内容。 IIRC,在超类之前总是会考虑外部类的上下文。在这种情况下,找到帮助者。但我们正在静态环境中构建价值(实际上是一个 private static final
之前 FOO
)。因此错误。
尝试 super.helper();
。
如果我将你的枚举翻译成它的类结构,它看起来大致如下:
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可以让你私有访问父级。
至于静态上下文错误,我同意错误消息似乎没有意义。
您可以将每个枚举常量视为枚举类的子类的唯一实例。就像“常规”类一样,枚举“子类”不能访问枚举“超类”的私有成员。 (我不能重新创建你提到的“这个”。)
一个合理的解决方案是 更改方法访问权限 私人的 至 保护 允许访问枚举常量“子类”。
更好的问题标题建议:“Java私有枚举方法?”或者只是“私有枚举方法”(让Java标记处理Java-ness)
有一个 文章 提到这个问题,不幸的是它是德语。也许你仍然可以提取一些有用的信息。
编辑:似乎与你的问题有些不同。我仍然不明白你的例子的行为,我也在这里看到。