这个问题是一个跟进: 为什么可以& #8217; t我在一个同名的匿名类之外调用一个方法

上一个问题回答为什么,但现在我想知道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) {
    }
}
有帮助吗?

解决方案

javac的这种行为符合规范。请参阅§ 15.12方法调用表达式在Java语言规范中,特别是“编译时间步骤1”下的段落。解释非限定方法调用的含义:

  

如果标识符出现在具有该名称的可见方法声明的范围(§ 6.3)内,则必须存在该方法所属的封闭类型声明。设T是最里面的类型声明。要搜索的类或接口是T.

换句话说,在所有封闭范围中搜索非限定方法 name ,并在最里面的“类型声明”中搜索。找到名称的(表示类或接口声明)是将搜索整个签名的名称(在“编译时间步骤2”中)。

其他提示

听起来像是一个含糊不清和脆弱的秘诀 - 只要在你的基类中添加一个新方法(好吧,对于一个接口来说不太可能......)你的代码的含义就会彻底改变。

匿名类已经非常丑陋 - 让这一点显而易见并不会让我感到烦恼。

尝试

NotApplicable.this.run(42);

代替。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top