聊聊一段讓人抓心撓肝的源碼
加了松哥微信的小伙伴可能注意到松哥前兩天發的一個朋友圈了,就是我在錄制 Spring 源碼的時候,發現了這樣一段代碼:
為了大家閱讀方便,我這里只貼出來一些關鍵的部分:
protected Object getObjectForBeanInstance(
Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
//省略
if (!(beanInstance instanceof FactoryBean<?> factoryBean)) {
return beanInstance;
}
//省略
if (object == null) {
//省略
object = getObjectFromFactoryBean(factoryBean, beanName, !synthetic);
}
return object;
}
這段代碼里有一個比較好玩的地方就是使用了 JDK16 中引入的增強類型推斷,以前我們用 instanceof 的時候可能是這樣:
if(a instanceof B){
B b = (B)a;
}
這樣比較麻煩,所以從 JDK16 開始,支持一種新的寫法,如下:
if(a instanceof B b){
//...
}
這段代碼跟上面的代碼的作用是一模一樣的。
最上面的 Spring 源碼其實就是用了這個最新的寫法。
但是!!!
我今天想和各位小伙伴聊的其實還不是這個問題,而是在上面的 Spring 源碼中,factoryBean 變量是在 if 分支中定義的,按理說,它的作用域就存在于 if 分支中,但是各位小伙伴注意,factoryBean 變量卻可以在下面的 if 中使用,這是咋回事呢?
大家看下下面這個截圖,這個是 Spring 框架在 2022.01.26 的提交日志,就是這一次提交修改了上面這個 getObjectForBeanInstance 方法:
圖片
從這段變更中,我們其實可以看到,在之前的 Spring 源碼中,是有專門的一行 FactoryBean<?> factory = (FactoryBean<?>) beanInstance; 去做類型轉換的,然后在接下來的方法中去使用該變量,但是現在沒有這樣一句了,很明顯,現在是在 if 中做 instanceof 判斷時順手定義的 factoryBean 變量,在下面的 if 分支中使用了,這和我們理解的 Java 中變量的作用域似乎不太一樣。
這是咋回事呢?
前兩天我發個朋友圈之后,有小伙伴說這是語法糖,這顯然不是,因為如果是語法糖,這很容易造成歧義,變量的作用域豈不是全亂了?
也有小伙伴說這是新特性,這個很聰明,不認識的寫法統一都是新特性。但是新在哪里?什么樣的情況下可以在 if 之外使用 if 判斷條件里聲明的變量?什么樣的情況下不可以?