Java模拟Function函数式接口时lambda与匿名内部类行为差异疑问
问题解答
两者行为差异的核心是作用域解析规则不同
代码片段B出现递归的原因
匿名内部类会创建独立的作用域,在匿名内部类内部调用无明确前缀的方法时,会优先匹配当前内部类自身定义的方法。你在自定义的SFunction匿名实现类中重写了apply(T t)方法,此时代码中的apply(t)会被解析为调用这个匿名内部类自己的apply方法,最终形成无限递归。
如果要让匿名内部类版本实现和Lambda相同的效果,只需要显式指定调用外部接口实例的方法即可,修改后代码如下:
return new SFunction<T, Q>() { @Override public Q apply(T t) { // 显式指定调用外层SFunction实例的apply方法 return after.apply(SFunction.this.apply(t)); } };
代码片段A运行正常的原因
Lambda表达式采用词法作用域,设计上不会创建独立的作用域层级,Lambda内部的所有符号引用都会直接从定义Lambda的上下文(也就是andThen方法所属的SFunction实例)进行解析。所以这里的apply(t)指向的是调用andThen方法的外层SFunction实例的apply方法,不会指向Lambda自身的实现,自然不会出现递归问题。
补充说明
你提到的「Java内部对Lambda也会生成类似匿名实现的结构」属于JVM层面的实现细节,但在Java语言规范层面,Lambda和匿名内部类的作用域解析规则从设计之初就有明确区别,这就是两者行为不一致的根本原因。
内容的提问来源于stack exchange,提问作者sumit
相关产品推荐
相关产品推荐

