这个问题是一个跟进: Why can’t I call a method outside of an anonymous class of the same name
上一个问题回答为什么,但现在我想知道javac 应该找到run(int bar)? (参见上一个问题,了解为什么run(42)失败)
如果不应该,是否由于规格?它会产生含糊不清的代码吗?我的观点是,我认为这是一个错误。虽然上一个问题解释了为什么这个代码无法编译,但我觉得如果javac在树中搜索得更高,如果它在当前级别找不到匹配项,它应该编译。 IE浏览器。如果this.run()不匹配,则应自动检查NotApplicable.this是否为run方法。
另请注意,正确找到了foo(int bar)。如果你给出任何不应该找到run(int bar)的理由,那么它也必须解释为什么找到foo(int bar)。
public class NotApplicable {
public NotApplicable() {
new Runnable() {
public void run() {
// this works just fine, it automatically used NotApplicable.this when it couldn't find this.foo
foo(42);
// this fails to compile, javac find this.run(), and it does not match
run(42);
// to force javac to find run(int bar) you must use the following
//NotApplicable.this.run(42);
}
};
}
private void run(int bar) {
}
public void foo(int bar) {
}
}
答案 0 :(得分:4)
javac的这种行为符合规范。请参阅Java语言规范中的§15.12 Method Invocation Expressions,特别是“编译时间步骤1”下的段落,解释了非限定方法调用的含义:
如果标识符出现在具有该名称的可见方法声明的范围(第6.3节)中,则必须存在该方法所属的封闭类型声明。设T是最里面的类型声明。要搜索的类或接口是T.
换句话说,在所有封闭的范围中搜索非限定方法 name ,并在其中找到名称的最里面的“类型声明”(表示类或接口声明)是将搜索整个签名的那个(在“编译时间步骤2”中)。
答案 1 :(得分:1)
听起来像是一个含糊不清和脆弱的秘诀 - 只要在你的基类中添加一个新方法(好吧,对于一个接口来说不太可能......)你的代码的含义就会完全改变。
匿名类已经非常丑陋 - 让这一点显而易见并不会让我感到烦恼。
答案 2 :(得分:1)
尝试
NotApplicable.this.run(42);
代替。