2015-01-31 25 views
2

Kotlin有漂亮的功能(?.!!.)處理可爲空的類型。但是這個只是打擊了我 - 如果你不知道你是在處理可爲空還是不可爲空的類型呢?如果你有泛型類MyClass<T>,那麼你只是有一些類型T,就是這樣。可以在泛型類中使用可爲空的運算符嗎?

不科特林允許有適用於通用型(T這裏)「可空」的運營商,也可製成型爲空的類(如T?),以及如果該類將可空類型的實例化 - 像MyClass<String?>。是否會在MyClass類型中導致可空(例如指向C++中指針的指針 - **std::string)類型的空?

+0

只是鍵入'T'被解釋爲'T:Any?',所以沒有「只輸入'T'」,因爲編譯器會將其視爲可空。您可以使用'T:Any'來定義不可空的不同上限。 – 2016-01-02 03:21:30

回答

5

我剛剛在Web Demo中試過。

class MyClass<T>(val x: T) { 
    fun foo() { 
    println(x.toString()) 
    } 

    fun fooSave() { 
    println(x?.toString()) 
    } 

} 

fun main(args: Array<String>) { 
    MyClass<String?>(null).fooSave() 
    MyClass<String?>(null).foo() 
} 

看來你可以隨時申請空安全操作員?.,即使類型不一定爲空。

在另一方面,你可以泛型類型參數T綁定到一個可空類型,在我的情況String? 這實際上如果你通過 null 會產生一個NullPointerException異常。

編輯:由於問題被問到,沒有上限的泛型類型的語義已經改變。現在將T解釋爲T : Any?。但是,上面的代碼不會崩潰了。原因是呼叫x.toString()將調用正確處理null的擴展功能Any?.toString()

如果我們改變了代碼如下

class MyClass<T : Any>(val x: T) { 
    fun foo() { 
    println(x.toString()) 
    } 

    fun fooSave() { 
    println(x?.toString()) 
    } 

} 

fun main(args: Array<String>) { 
    MyClass<String?>(null).fooSave() 
    MyClass<String?>(null).foo() 
} 

現在甚至不進行編譯,因爲我們不能String?實例T : Any。呼叫x?.toString()也標有警告,表示安全呼叫是不必要的。

+0

哇,如果我可以,我會爲該鏈接添加更多點:-)非常感謝。更重要的是 - 你剛剛發現,針對null的顯式實際上並不起作用。如果沒有泛型,你將不得不編寫'!!。toString()',但是泛型編譯器不知道'T'是什麼,並且允許隱式檢查。 – greenoldman 2015-02-01 14:01:51

+1

第二次檢查時,這個例子是特例,因爲toString是在根類型中定義的。這就是爲什麼(可能)它首先編譯的原因 - 任何其他方法(如「length」)都需要爲泛型添加約束,這意味着您必須事先決定您編寫泛型類的類型 - 可爲空還是不可以。 – greenoldman 2015-02-01 14:43:09

+1

你說得對。如果我設置T來擴展任何類型,我不能將它綁定到可空類型,因爲T?不延伸T.這是一個不能編譯的例子:http://kotlin-demo.jetbrains.com/?publicLink=1174338469563409828491677856014 – 2015-02-01 14:46:29

相關問題