簡體   English   中英

Java三元運算符vs <JDK8兼容性中的if / else

[英]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.methodthis.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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM