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()
进行编译......)
答案 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提到这个问题,遗憾的是它是用德语写的。也许你仍然可以提取一些有用的信息。
编辑:似乎与你的问题有些不同。我仍然不明白你的例子的行为,我也在这里看到。