聊一聊泛型的可空性(kotlin)
什麼?泛型本身也可以是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
是否有所瞭解?
相關文章
- 【修煉內功】[kotlin] 聊一聊泛型的可空性Kotlin泛型
- Kotlin教程(四)可空性Kotlin
- 聊一聊 JVM 的 GCJVMGC
- 聊一聊 RestTemplateREST
- 聊一聊設計模式(二)-- 建立型設計模式設計模式
- 聊一聊 Javascript 中的 ASTJavaScriptAST
- 聊一聊 TLS/SSLTLS
- 聊一聊設計模式(四)-- 行為型設計模式設計模式
- 聊一聊設計模式(三)-- 結構型設計模式設計模式
- 聊一聊Javascript中的Promise物件JavaScriptPromise物件
- 簡單聊一聊Vuex的原理Vue
- 聊一聊Java的列舉enumJava
- 聊一聊遊戲的壓測遊戲
- 聊一聊MySQL的字符集MySql
- 聊一聊MySQL的儲存引擎MySql儲存引擎
- 聊一聊MySQL的直方圖MySql直方圖
- 聊一聊Redis的離線分析Redis
- 聊一聊Jmeter的引數化JMeter
- 聊一聊橋接(JSBridge)的原理橋接JS
- Kotlin中的泛型Kotlin泛型
- 聊一聊前端換膚前端
- 聊一聊session和cookieSessionCookie
- 聊一聊Greenplum與PostgreSQLSQL
- 聊一聊模板方法模式模式
- 聊一聊測試流程
- 聊一聊redis十種資料型別及底層原理Redis資料型別
- 聊一聊Iterable與Iterator的那些事!
- 聊一聊Spring Bean 的生命週期SpringBean
- 聊一聊RocketMQ的註冊中心NameServerMQServer
- 聊一聊MySQL索引失效的問題MySql索引
- [gRPC]來聊一聊gRPC的認證RPC
- 聊一聊 SQLSERVER 的行不能跨頁SQLServer
- Nginx-01-聊一聊 nginxNginx
- 聊一聊介面卡模式模式
- 聊一聊隨機數安全隨機
- 聊一聊SQL最佳化SQL
- 聊一聊系統重構
- 聊一聊過度設計!