当前位置: 首页 > article >正文

解析springboot源码中this::selfInitialize怪异用法的含义

最近在看springboot源码中有一段很怪异的代码

  private ServletContextInitializer getSelfInitializer() {
        return this::selfInitialize;
    }

 

 按照通常的java 8 lambda理解: 双冒号无法就是方法调用的另一中写法,那么this::selfInitialize就是调用selfInitialize方法,但是这个方法不是返回void吗,为什么getSelfInitializer方法调用了这个方法还能返回ServletContextInitializer,从而继续执行onStartup方法呢?

是不是觉得非常奇怪,很难理解。 

于是,先简单断点调试一下,看一下getSelfInitializer方法返回值到底是什么:

从上面的getWebServer进来:

 

 可以看到initializers(也就是getSelfInitializer返回值,就是个数组)的元素类型是一个lambda表达式,它的入参类型是AnnotationConfigServletWebServerApplicationContext

AnnotationConfigServletWebServerApplicationContext的父类是ServletWebServerApplicationContext(也就是getSelfInitializer方法所在的类),其实也就是this

 

 那么可以推断this::selfInitialize相当于是整个被作为参数传递给了lambda表达式

为什么会有这种用法呢?

@FunctionalInterface
public interface ServletContextInitializer {
    void onStartup(ServletContext servletContext) throws ServletException;
}

可以看到ServletContextInitializer是一个函数式接口:

这里提两个重要的知识点

1. 函数式接口只能有一个抽象方法(只是因为接口内部:定义方法时可以省略abstract关键字)。
2.  Lambda表达式就是一个函数式接口的实例,Lambda表达式也是函数式接口所定义方法的实现

所以,考虑到getSelfInitializer方法的返回值是ServletContextInitializer,那么this::selfInitialize这种lambda表达式的写法相当于下面的匿名内部类的代码:

new ServletContextInitializer() {
    @Override
    void onStartup(ServletContext servletContext) throws ServletException {
          selfInitialize(servletContext);
     };
}

this::selfInitialize是把selfInitialize方法作为整体作为参数传递给了lambda表达式,重写了ServletContextInitializer接口的onStartup方法的内部方法体。

所以,像this::${method}这种用法,通常是把method方法作为参数传递给lambda表达式达到重写函数式接口方法的目的,此时一定要看一下this::${method}所在方法的返回值类型,这个返回值类型就是函数式接口的类型。

总而言之: Lambda表达式的引入降低了代码的可读性,远没有匿名内部类(@override)那么清晰, java的函数式编程做的很烂,感觉就是一个生搬硬凑的破烂玩具,没有javascript做的好。


http://www.kler.cn/a/4787.html

相关文章:

  • 基于STM32的智能家居蓝牙系统(论文+源码)
  • nvim 打造成可用的IDE(2)
  • Postman接口测试03|执行接口测试、全局变量和环境变量、接口关联、动态参数、断言
  • C++11右值引用
  • 华为OD机试用java实现 -【吃火锅】
  • ChatGPT辅助编程实践——常用提示词整理
  • CentOS从gcc 4.8.5 升级到gcc 8.3.1
  • 初识Kafka
  • 八. MySQL 成本计算与执行优化器优化步骤
  • 1014 福尔摩斯的约会
  • 下一代的新操作系统就是ChatGPT!
  • 最值得入手的五款骨传导耳机,几款高畅销的骨传导耳机
  • 我的第一台手提 | 关于你的第一台手提征文活动
  • PyTorch加载自己的数据集
  • 第一台电脑(创作活动水点经验)
  • 电电电电电电电电要来了!
  • Unity——λ表达式(匿名函数)/Linq/回调函数
  • Ajax 入门
  • 如何用秒验提升用户体验和转换率?
  • 分享:从ChatGPT给到的数据库故障案例,看开发协同未来趋势
  • 使用Selenium和Chrome浏览器获取诗词网站搜索结果
  • c语言结构体详解
  • 200.Spark(七):SparkSQL项目实战