springboot源码中this::selfInitialize怪异用法的含义解析
作者:kingtopest
最近在看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. 函数式接口只能有一个方法。
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做的好。
到此这篇关于springboot源码中this::selfInitialize怪异用法的含义的文章就介绍到这了,更多相关springboot this::selfInitialize用法内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!