根據Kotlin docs,?。運算符表示「安全調用」,這意味着如果它用於方法調用鏈中,則整個鏈將返回null(如果它使用的值爲null)。什麼?在Kotlin中是否指派任務的左側?
但是如果它在任務的左側使用呢?由於左側不是「返回」任何一方,因此它可能具有不同的效果。下面是我在談論的一個例子:
val myObj = SomeObj()
myObj?.property = SomeClass.someFunc() // What does ?. do in this context?
根據Kotlin docs,?。運算符表示「安全調用」,這意味着如果它用於方法調用鏈中,則整個鏈將返回null(如果它使用的值爲null)。什麼?在Kotlin中是否指派任務的左側?
但是如果它在任務的左側使用呢?由於左側不是「返回」任何一方,因此它可能具有不同的效果。下面是我在談論的一個例子:
val myObj = SomeObj()
myObj?.property = SomeClass.someFunc() // What does ?. do in this context?
這意味着,如果在左側的安全調用一個失敗(即它的接收器爲空),那麼整個分配跳過,在右邊的表達根本不被評估。
val nullable: Container? = null
nullable?.x = f() // f is not called
我剛纔看到在科特林一個有趣的問題&答案。即使答案非常好,但我想更詳細地澄清它。
分配以下表達式:
myObj?.property = SomeClass.someFunc()
由歌林如下轉化成Java字節碼:
val it = myObj;
if(it != null){
it.property = SomeClass.someFunc();
}
所以在多個線程中沒有問題。它仍然正常工作,我已經在github上測試過它。但是這會導致Thread Interference問題,這意味着當myObj
發生更改時,它將在不同的引用上修改property
。
除了賦值表達式可短路,其他還可以是短路。例如:
val array:Array<Any>? = null;
// v--- short-circuited
array?.set(0,SomeClass.someFunc());
// ^--- never be called
這很有趣,因爲在您將某些值分配給基於其自身的值的情況下,您仍然必須在右側使用它以避免編譯器錯誤。 (例如,myObj?.property = myObj?.property + 1) – Sonofblip
@Sonofblip,這裏有一個不同的原因:在一個多線程環境中(一個JVM),一個全局變量'myObj'可以被重新分配在左側,並在右側評估「myObj?.property」。所以,你需要再次檢查。 – hotkey
@hotkey先生,第一次表決。但它不需要在多線程中再次檢查它,因爲kotlin會將引用複製到另一個變量中。 –