4

这个问题是后续问题: 为什么我不能在同名的匿名类之外调用方法

这个先前的问题回答了为什么,但现在我想知道 javac是否应该找到 run(int bar)?(请参阅上一个问题以了解 run(42) 失败的原因)

如果不应该,是因为规范吗?它会产生模棱两可的代码吗?我的意思是,我认为这是一个错误。虽然前面的问题解释了为什么这段代码无法编译,但我觉得如果 javac 在树中搜索更高的位置,如果它未能在当前级别找到匹配项,它应该编译。IE。如果 this.run() 不匹配,它应该自动检查 NotApplicable.this 是否有运行方法。

另请注意,正确找到了 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) {
    }
}
4

3 回答 3

4

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

如果标识符出现在具有该名称的可见方法声明的范围(第 6.3 节)内,则必须存在该方法是其成员的封闭类型声明。让 T 成为最里面的这种类型声明。要搜索的类或接口是 T。

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

于 2008-10-31T17:33:50.020 回答
1

对我来说,这听起来像是一个模棱两可和脆弱的秘诀——一旦在你的基类中添加了一个新方法(好吧,对于接口来说不太可能......)你的代码的含义就会完全改变。

匿名类已经很丑陋了——让这点显式一点也不困扰我。

于 2008-10-31T17:19:03.403 回答
1

尝试

NotApplicable.this.run(42);

反而。

于 2008-10-31T17:37:20.280 回答