javac应该在同名的匿名类之外找到方法吗?

时间:2008-10-31 17:15:49

标签: java methods javac anonymous-class

这个问题是一个跟进: 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) {
    }
}

3 个答案:

答案 0 :(得分:4)

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

  

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

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

答案 1 :(得分:1)

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

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

答案 2 :(得分:1)

尝试

NotApplicable.this.run(42);

代替。