最后的代码产生编译错误:

NotApplicable.java:7: run() in  cannot be applied to (int)
                run(42);
                ^
1 error

问题是为什么?为什么javac认为我调用run(),并且找不到run(int bar)?它正确地称为foo(int bar)。为什么我必须使用NotApplicable.this.run(42);?这是一个错误吗?

public class NotApplicable {

    public NotApplicable() {
        new Runnable() {
            public void run() {
                foo(42);
                run(42);
                // uncomment below to fix
                //NotApplicable.this.run(42);
            }
        };
    }

    private void run(int bar) {
    }

    public void foo(int bar) {
    }
}
有帮助吗?

解决方案

代码示例行为的解释是 this 被定义为您当前“最”的类。代替。在这种情况下,你是“最”的在子类runnable的匿名内部类中,没有匹配 run(int)的方法。要扩大搜索范围,请通过声明 NotApplicable.this.run(42)来指定要使用的 this

jvm将评估如下:

this - >当前正在使用方法 run()执行 Runnable 的实例

NotApplicable.this - >当前使用方法 run(int)执行 NotApplicable 的实例

编译器将查找嵌套树以查找与方法的NAME匹配的第一个方法。 –感谢DJClayworth的澄清

匿名内部类不是外部类的子类。由于这种关系,内部类和外部类都应该能够拥有一个具有完全相同签名的方法,并且最里面的代码块应该能够识别它想要运行的方法。

public class Outer{

    public Outer() {
        new Runnable() {
            public void printit() {
                System.out.println( "Anonymous Inner" );
            }
            public void run() {
                printit(); // prints "Anonymous Inner"
                this.printit(); //prints "Anonymous Inner"

                // would not be possible to execute next line without this behavior
                Outer.this.printit(); //prints "Outer" 
            }
        };
    }

    public void printit() {
        System.out.println( "Outer" );
    }
}

其他提示

据我所知,选择在嵌套类之间运行的方法的规则与在继承树中选择方法的规则大致相同。这意味着我们在这里得到的不是超载,它隐藏着。这些之间的区别对于理解继承中的方法至关重要。

如果您的Runnable被声明为子类,则run()方法将隐藏父级中的run(int)方法。任何对run(...)的调用都会尝试在Runnable上执行,但如果无法匹配签名则会失败。由于未在子节点中声明foo,因此调用父节点上的foo。

同样的原则在这里发生。查找对“方法隐藏”的引用它应该是清楚的。

这是因为当您输入 new Runnable(){} 范围时,将重新声明 run 。以前运行的所有绑定都无法访问。就好像你这样做:

import java.util.*;

public class tmp
{
  private int x = 20;
  public static class Inner
  {
      private List x = new ArrayList();
      public void func()
      {
          System.out.println(x + 10);
      }
  }

  public static void main(String[] args)
  {
    (new Inner()).func();
  }
}

编译器不会在范围堆栈中查找与 x 类型相匹配的内容,只有在找到第一个引用并且看到类型不兼容时才会停止

注意:这不像是无法这样做......只是为了保持自己的理智,已经决定不应该这样做

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