本文已收錄【修煉內功】躍遷之路
什麼?泛型本身也可以是nullable?上來就拋這麼個問題實在是不夠友好~
首先回顧,什麼是泛型?Oracle Java Tutorials
Introduced in J2SE 5.0, this long-awaited enhancement to the type system allows a type or method to operate on objects of various types while providing compile-time type safety. It adds compile-time type safety to the Collections Framework and eliminates the drudgery of casting.
泛型的本質是引數化型別,也就是說操作的資料型別被指定為一個引數。簡單來講,泛型就是操作型別的佔位符。
那,為什麼要使用泛型?Oracle Java Tutorials
In a nutshell, generics enable types (classes and interfaces) to be parameters when defining classes, interfaces and methods. Much like the more familiar formal parameters used in method declarations, type parameters provide a way for you to re-use the same code with different inputs. The difference is that the inputs to formal parameters are values, while the inputs to type parameters are types.
泛型的好處是在編譯的時候做型別安全檢查,並且所有的強制轉換都是自動和隱式的,提高程式碼的重用率。
在深入討論泛型的可空性之前,首先看一個簡單的例子 (kotlin中更多泛型的介紹,以及其與java泛型的區別,可以檢視Generics)
fun <T> whoAmI(t: T) {
val clazz = t::class
println("I'm $clazz")
}
上面的程式碼是編譯不過的,問題在於
nullable type 'T'
是什麼鬼?OK,我們按照提示,為引數t加上!!
強制標識為not-null (關於!!
的使用,可以檢視Null Safety)
WTF~ 嗶~ 卒~
在繼續討論之前,先關注兩個概念,type parameter
和type argument
,在一個函式中,前者是函式引數的型別(型別),如translate(java.lang.String, java.lang.String)
中的java.lang.String
,而後者則是函式呼叫時傳入的具體值(型別),如translate("Hello You!", "zh-cn")
中的Hello You
及zh-cn
,泛型作為一個佔位符,佔的正是type parameter
的位
首先簡單瞭解一下argument
的可空性,kotlin中控制函式引數值(類屬性值等)的nullable是透過?
符號實現的,預設均為non-nullable,如以下程式碼片段是編譯不過的
只有指定引數name
為nullable,才可以順利編譯
同樣,對應泛型類,我們也可以指定nullable及non-nullable的type argument
從上例中可以看到,null
在kotlin中的型別為Nothing?
(kotlin中一切皆為物件)
更多內容請參考 Null Safety
說了這麼多,到底什麼是泛型的可空性(type argument
的nullable
)?
上例中,之所以可以將forestA
指定為Forest<Tree?>
,是因為,每一個nullable
的type argument
都有一個隱式邊界Any?
,即如下兩種類宣告完全等價
// T的隱式邊界為Any?
class Forest<T>
// 顯示指定T的邊界為Any?
class Forest<T : Any?>
// 顯示指定T的邊界為Tree?
class Forest<T : Tree?>
如果將Forest
中的泛型強制指定為non-nullable會發生什麼
什麼?不能將nullable的Tree?
應用到Forest
類了!這是因為Forest
類的定義中,我們強制將泛型的邊界指定為了non-nullable的Tree
所以,回到文章的開頭,函式whoAmI
的錯誤資訊nullable type 'T'
指的是哪個鬼?泛型T
的預設邊界為Any?
,即T : Any?
,所以,我們只需要顯示指定T
為non-nullable即可
至此,對於nullable
及non-nullable
的type parameter
及type argument
是否有所瞭解?