[英]Java ternary operator vs if/else in <JDK8 compatibility
最近我正在閱讀Spring Framework的源代碼。 我無法理解的東西在這里:
public Member getMember() {
// NOTE: no ternary expression to retain JDK <8 compatibility even when using
// the JDK 8 compiler (potentially selecting java.lang.reflect.Executable
// as common type, with that new base class not available on older JDKs)
if (this.method != null) {
return this.method;
}
else {
return this.constructor;
}
}
此方法是org.springframework.core.MethodParameter
類的成員。 代碼很容易理解,而評論很難。
注意:即使使用JDK 8編譯器,也沒有三元表達式來保持JDK <8的兼容性(可能選擇
java.lang.reflect.Executable
作為通用類型,舊的JDK上沒有新的基類)
使用三元表達式和在此上下文中使用if...else...
構造有什么區別?
當您考慮操作數的類型時,問題變得更加明顯:
this.method != null ? this.method : this.constructor
具有兩種操作數的最專業的常見類型,即this.method
和this.constructor
共有的最特殊類型。
在Java 7中,這是java.lang.reflect.Member
,但Java 8類庫引入了一種新的類型java.lang.reflect.Executable
,它比通用Member
更專業。 因此,對於Java 8類庫,三元表達式的結果類型是Executable
而不是Member
。
在編譯三元運算符時,Java 8編譯器的某些(預發布)版本似乎在生成的代碼中生成了對Executable
的顯式引用。 這將觸發類加載,因此在運行時使用類庫<JDK 8時會在運行時觸發ClassNotFoundException
,因為只有Executable
才存在。
正如Tagir Valeev在本回答中所指出的,這實際上是JDK 8預發布版本中的一個錯誤,並且已經修復,因此if-else
解決方法和解釋性注釋現在都已過時。
附加說明:有人可能得出結論,這個編譯器錯誤出現在Java 8之前。但是,OpenJDK 7為三元生成的字節代碼與OpenJDK 8生成的字節代碼相同。實際上,類型為表達式在運行時完全沒有提及,代碼實際上只是測試,分支,加載,返回而不進行任何額外的檢查。 所以請放心,這不再是問題(在Java 8的開發過程中確實似乎是一個臨時問題)。
這是在2013年5月3日相當舊的提交中引入的,差不多在官方JDK-8發布之前一年。 編譯器在那些時候處於大量開發階段,因此可能會出現這種兼容性問題。 我猜,Spring團隊剛剛測試了JDK-8版本並嘗試修復問題,即使它們實際上是編譯器問題。 通過JDK-8官方發布,這變得無關緊要。 現在,此代碼中的三元運算符可以正常工作(不存在對已編譯的.class文件中的Executable
類的引用)。
目前在JDK-9中出現類似的東西:JDK-8中可以很好地編譯的一些代碼在JDK-9 javac中失敗了。 我猜,大多數此類問題將在發布之前修復。
主要區別在於if
else
塊是一個語句,而三元(通常稱為Java中的條件運算符)是一個表達式 。
語句可以執行某些操作,例如在某些控制路徑上return
調用方。 表達式可用於賦值:
int n = condition ? 3 : 2;
因此條件之后的三元中的兩個表達式需要可強制轉換為相同類型。 這可能會導致Java中的一些奇怪的效果,尤其是自動裝箱和自動參考投射 - 這就是您發布的代碼中的注釋所指的內容。 在您的情況下,表達式的強制將是java.lang.reflect.Executable
類型(因為這是最專業的類型 ),並且在舊版本的Java中不存在。
從風格上講,如果代碼類似於語句,則應使用if
else
塊,如果類似於表達式,則應使用三元組。
當然,如果使用lambda函數,則可以使if
else
塊的行為類似於表達式。
三元表達式中的返回值類型受父類的影響,父類按Java 8中的描述進行更改。
很難理解為什么不能寫一個演員。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.