【kotlin 】內(nèi)聯(lián)類(value class / inline class)

官方文檔:https://kotlinlang.org/docs/inline-classes.html

注:inline class 關(guān)鍵字已經(jīng)被廢棄,取而代之的是value class∪ゼ現(xiàn)在使用內(nèi)聯(lián)類需要定義類為value class,并使用@JvmInline注解進(jìn)行標(biāo)注褂乍。

一、使用場景

有時(shí)候即硼,根據(jù)業(yè)務(wù)需求树叽,我們需要一些包裝類。但是谦絮,包裝類在運(yùn)行時(shí)會(huì)造成一些不可避免的額外開支题诵,比如堆上分配的額外空間洁仗。尤其是對于基本類型的包裝類——因?yàn)榛绢愋驮谶\(yùn)行時(shí)會(huì)有很多其他優(yōu)化,而包裝類型沒有性锭。于是赠潦,內(nèi)聯(lián)類便應(yīng)運(yùn)而生了。

內(nèi)聯(lián)類在編碼時(shí)作為一個(gè)其他類型的包裝類使用草冈,而在運(yùn)行時(shí)會(huì)被拆開作為其內(nèi)部值類型使用她奥。

例如,當(dāng)我們設(shè)計(jì)了一個(gè)動(dòng)畫:

class Animation(duration: Int) {
    // ...
}

duration 參數(shù)可能會(huì)讓人迷惑:它的單位是什么怎棱?秒或者毫秒哩俭?(雖然注釋可以解決一切問題,但它不在討論范圍之內(nèi))這個(gè)時(shí)候拳恋,就可以用到內(nèi)聯(lián)類凡资。

我們可以創(chuàng)建一系列的內(nèi)聯(lián)類,來表示不同的時(shí)間單位:

@JvmInline
value class Millis(val value: Int) 
@JvmInline
value class Second(val value: Int)
// ...

假使 duration 參數(shù)單位是毫秒谬运,那么將其類型修改為 Millis 類型即可:

class Animation(duration: Millis) {
    // ...
}

這樣隙赁,當(dāng)創(chuàng)建 Animation 對象的時(shí)候,就需要強(qiáng)制傳入一個(gè) Millis 類型的對象梆暖;如果傳入的是一個(gè) Second 類型的對象伞访,編譯器就會(huì)報(bào)錯(cuò)。

二轰驳、內(nèi)聯(lián)類允許的成員

內(nèi)聯(lián)類允許函數(shù)厚掷、init 塊、以及沒有 backing field 的屬性级解。

@JvmInline
value class Name(val s: String) {
    init {
        require(s.length > 0) { }
    }

    val length: Int
        get() = s.length

    fun greet() {
        println("Hello, $s")
    }
}

fun main() {
    val name = Name("Kotlin")
    name.greet() // method `greet` is called as a static method
    println(name.length) // property getter is called as a static method
}

三冒黑、內(nèi)聯(lián)類和普通包裝類的區(qū)別

對于原生類型來說,在運(yùn)行時(shí)會(huì)進(jìn)行大量的優(yōu)化蠕趁,而包裝類不會(huì)進(jìn)行處理薛闪。
而內(nèi)聯(lián)類在運(yùn)行時(shí)辛馆,會(huì)自動(dòng)使用內(nèi)聯(lián)類型而不是包裝類型進(jìn)行處理俺陋。

例如以下例子中:

// 毫秒
inline class Millisecond(val value: Long)

private fun doSomething(millisecond: Millisecond) {
    Log.i(TAG, "doSomething: $millisecond")
}

通過 IDE 的 Kotlin 字節(jié)碼反編譯功能,可以看到昙篙,生成的 Kotlin 字節(jié)碼已經(jīng)沒有 Millisecond 類型了腊状,而是直接使用的 Long 類型:

內(nèi)聯(lián)類反編譯結(jié)果

而普通的包裝類則不會(huì)進(jìn)行如此優(yōu)化:

class LongWrapper(val millis: Long)

private fun doSomething2(millisecond: LongWrapper) {
    Log.i(TAG, "doSomething: $millisecond")
}
包裝類反編譯結(jié)果

四、其他

1. 繼承

內(nèi)聯(lián)類只允許繼承接口苔可,而不允許繼承類缴挖,也不允許被其他類繼承。

2. 與 typealias 的相比

在讀取值的時(shí)候焚辅,value classtypealias 起到了類似的作用映屋;但是苟鸯,當(dāng)進(jìn)行賦值的時(shí)候,情況就變得不一樣了棚点。

假設(shè)我們現(xiàn)在使用一個(gè)類型 Name早处,表示一個(gè)字符串值。同時(shí)瘫析,有兩個(gè)函數(shù) setStringsetName

fun setName(name: Name) {}
fun setString(string: String) {}

在使用 typealias 的情況下砌梆,不管是 setString 還是 setName,均可以傳入 Name 或是 String 類型的參數(shù):

typealias Name = String
fun main() {
    val name: Name = "Bob"
    setName("Bob") // √
    setString(name) // √
}

但是贬循,如果使用的是內(nèi)聯(lián)類咸包,則二者均是不被允許的:

@JvmInline
value class Name(value: String)
fun main() {
    val name: Name = "Bob"
    setName("Bob") // ×
    setString(name) // ×
}

五、總結(jié)

  • 內(nèi)聯(lián)類相當(dāng)于一個(gè)包裝類杖虾,但是在編譯時(shí)會(huì)自動(dòng)進(jìn)行拆包使用內(nèi)部數(shù)據(jù)類型烂瘫。
  • 在實(shí)際使用中,和普通包裝類相同。
  • 內(nèi)聯(lián)類最大的優(yōu)點(diǎn)在于對于基本類型的包裝不會(huì)消耗額外的性能。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末代箭,一起剝皮案震驚了整個(gè)濱河市辨赐,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌襟锐,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,509評論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異注竿,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)魂贬,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,806評論 3 394
  • 文/潘曉璐 我一進(jìn)店門巩割,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人付燥,你說我怎么就攤上這事宣谈。” “怎么了键科?”我有些...
    開封第一講書人閱讀 163,875評論 0 354
  • 文/不壞的土叔 我叫張陵闻丑,是天一觀的道長。 經(jīng)常有香客問我勋颖,道長嗦嗡,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,441評論 1 293
  • 正文 為了忘掉前任饭玲,我火速辦了婚禮侥祭,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己矮冬,他們只是感情好谈宛,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,488評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著胎署,像睡著了一般入挣。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上硝拧,一...
    開封第一講書人閱讀 51,365評論 1 302
  • 那天径筏,我揣著相機(jī)與錄音,去河邊找鬼障陶。 笑死滋恬,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的抱究。 我是一名探鬼主播恢氯,決...
    沈念sama閱讀 40,190評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼鼓寺!你這毒婦竟也來了勋拟?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,062評論 0 276
  • 序言:老撾萬榮一對情侶失蹤妈候,失蹤者是張志新(化名)和其女友劉穎敢靡,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體苦银,經(jīng)...
    沈念sama閱讀 45,500評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡啸胧,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,706評論 3 335
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了幔虏。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片纺念。...
    茶點(diǎn)故事閱讀 39,834評論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖想括,靈堂內(nèi)的尸體忽然破棺而出陷谱,到底是詐尸還是另有隱情,我是刑警寧澤瑟蜈,帶...
    沈念sama閱讀 35,559評論 5 345
  • 正文 年R本政府宣布烟逊,位于F島的核電站,受9級特大地震影響踪栋,放射性物質(zhì)發(fā)生泄漏焙格。R本人自食惡果不足惜图毕,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,167評論 3 328
  • 文/蒙蒙 一夷都、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦囤官、人聲如沸冬阳。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,779評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽肝陪。三九已至,卻和暖如春刑顺,著一層夾襖步出監(jiān)牢的瞬間氯窍,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,912評論 1 269
  • 我被黑心中介騙來泰國打工蹲堂, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留狼讨,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,958評論 2 370
  • 正文 我出身青樓柒竞,卻偏偏與公主長得像政供,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子朽基,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,779評論 2 354

推薦閱讀更多精彩內(nèi)容