2017-04-15 21 views
2

在Kotlin中執行代碼的慣用方法是什麼?一個變量的返回值,顯然可以爲null,但實際上不可能

private var someVar: SomeClass? = null 

    private fun getSomeVar(): SomeClass { 
     if (someVar == null) { 
      someVar = getDefaultSomeVar() 
     } 

     return someVar 
    } 

Android Studio警告我關於返回類型。然而,在Java中,這個代碼是適當的和慣用的。我的意思是,而不是將返回類型更改爲SomeClass?也許還有更好的方法?

其實,getSomeVar()永遠不能返回null

+1

有什麼警告?首選項在哪裏? –

回答

0

你可以寫:

return someVar!! 

這將返回一個非空值,但是如果它爲空,將拋出NPE。

5

編譯器抱怨,因爲理論上,不同的線程可能會在賦值語句和返回語句之間更改someVar

這裏的慣用解決方案是使用property delegation

private val someVar: SomeClass by lazy { getDefaultSomeVar() } 

這初始化時,它在一個線程安全的方式是第一次訪問屬性。還要注意,它現在是一個不可空的val,而不是一個可爲空的var,這使得它通常更容易處理。

您確實失去了稍後修改它的能力。如果它需要變化,你現在必須自己做。示例實現看到這個SO問題:Kotlin lazy default property


以下兩種解決方案採取方法的問題(即「Java的方式」)是理所當然的,只是顯示方式,以防止編譯器警告。然而,在你的情況下,這些是而不是建議,因爲他們都有懶惰初始化屬性的缺點:

1)引入一個局部變量。這個變量是安全,不會被其他線程正在發生突變,並允許編譯器做一個聰明的演員:

private fun getSomeVar(): SomeClass { 
    var value = someVar 
    if(value == null) { 
     value = getDefaultSomeVar() 
     someVar = value 
    } 

    return value 
} 

的方法本身仍不過不是線程安全的。在多線程環境中,可以多次調用getDefaultSomeVar(),並且不保證此方法的返回值等於someVar

2)使用!!:double bang操作符。這將可空類型轉換爲不可空。但是現在你失去了kotlin編譯器對你執行的保護和null safety

return someVar!! 

由於文檔所說的那樣:「如果你想要一個NPE,你可以把它」

+0

您的解決方案1不會阻止'someVar = value'和'return value'之間的'someVar'修改。所以'getSomeVar()'的調用者的返回值可能與變量的實際值不同。所以這應該真的被改爲一個懶惰的初始化val,正如你所建議的那樣。 –

+0

@PJMeisch你是對的,謝謝。我編輯了答案也反映了這一點。 – RobCo

0

這可能是短,沒有任何警告

private fun getSomeVar(): SomeClass { 
     return someVar?:getDefaultSomeVar() 
    }