2017-06-16 13 views
21

根據Kotlin docs,?。運算符表示「安全調用」,這意味着如果它用於方法調用鏈中,則整個鏈將返回null(如果它使用的值爲null)。什麼?在Kotlin中是否指派任務的左側?

但是如果它在任務的左側使用呢?由於左側不是「返回」任何一方,因此它可能具有不同的效果。下面是我在談論的一個例子:

val myObj = SomeObj() 
myObj?.property = SomeClass.someFunc() // What does ?. do in this context? 

回答

27

這意味着,如果在左側的安全調用一個失敗(即它的接收器爲空),那麼整個分配跳過,在右邊的表達根本不被評估。

val nullable: Container? = null 
nullable?.x = f() // f is not called 

(runnable demo)

+0

這很有趣,因爲在您將某些值分配給基於其自身的值的情況下,您仍然必須在右側使用它以避免編譯器錯誤。 (例如,myObj?.property = myObj?.property + 1) – Sonofblip

+4

@Sonofblip,這裏有一個不同的原因:在一個多線程環境中(一個JVM),一個全局變量'myObj'可以被重新分配在左側,並在右側評估「myObj?.property」。所以,你需要再次檢查。 – hotkey

+0

@hotkey先生,第一次表決。但它不需要在多線程中再次檢查它,因爲kotlin會將引用複製到另一個變量中。 –

2

我剛纔看到在科特林一個有趣的問題&答案。即使答案非常好,但我想更詳細地澄清它。

分配以下表達式:

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