从匿名内部类调用被重写的默认方法的编译问题
Why does the lambda work but the anonymous inner class fail to compile when calling
A.super.doA()? 这个问题的核心差异,在于Lambda表达式和匿名内部类对外部实例上下文的绑定规则完全不一样,咱们掰开了说:
先看Lambda的情况
当你写() -> A.super.doA()的时候,这个Lambda并没有创建一个独立的类实例——它更像是当前Test对象的一段"代码片段",直接复用了外部Test实例的上下文。所以这里的A.super.doA(),编译器会直接理解为:调用当前Test实例所实现的接口A的默认方法,和你在Test::doA()方法里直接写A.super.doA()是完全一样的逻辑,自然能正常编译运行。
再看匿名内部类的问题
匿名内部类是一个全新的、独立的类实例,它有自己的命名空间和上下文。当你在这个内部类里写A.super.doA()时,编译器会默认认为你是想调用这个匿名内部类自己实现的接口A的超类方法——但尴尬的是,这个匿名内部类只实现了接口B,根本没有实现A!所以编译器找不到对应的A.super,直接就报错了。
如果想让匿名内部类的写法也能工作,你需要显式指定要访问的是外部Test实例的接口A超类方法,写法如下:
new B() { public void doB() { Test.this.A.super.doA(); // 显式指定外部Test实例的A接口超类方法 } }.doB();
总结一下
- Lambda是上下文透明的,它直接沿用外部实例/方法的上下文,不需要额外指定就能访问外部实例的接口超类方法;
- 匿名内部类是独立的类实例,有自己的上下文边界,必须通过
外部类.this.接口.super.方法的显式语法,才能访问外部实例的接口超类方法。
内容的提问来源于stack exchange,提问作者Alexander Torstling
相关产品推荐
相关产品推荐

