Kotlin語法-內(nèi)聯(lián)函數(shù)

前景

2020年3月31號(hào),androidDeveloper介紹了Kotlin特性內(nèi)聯(lián)函數(shù),主要是用kotlin語法糖+編譯器處理,優(yōu)化了方法棧以及方法對(duì)象的生成。這章節(jié)我們來探究下Kotlin的inline修飾符的真面目。

介紹

inline修飾符
  1. 首先要inline修飾符的用法,官網(wǎng)只推薦我們的函數(shù)塊里包含函數(shù)作為參數(shù)時(shí)候使用inline修飾符。
//編譯器警告刪除inline修飾符,因?yàn)閕nline修飾符是為了函數(shù)參數(shù)做優(yōu)化的
inline fun inlineFunction(a: Int): Void {
        val bb = 1 + 3
        val cc = 3 + 5
    }

//當(dāng)參數(shù)中有函數(shù)作為參數(shù)時(shí)候,編譯器就會(huì)認(rèn)同inline修飾的函數(shù)
inline fun inlineFunction(a: Int, block: () -> Unit): Void {
        block()
        val bb = 1 + 3
        val cc = 3 + 5
    }
從反編譯的java層分析inline修飾符
  1. 為了能看出inline修飾符的作用,我們寫了兩個(gè)一模一樣的函數(shù),一個(gè)用inline修飾符,另外一個(gè)不用inline修飾符。從Kotlin反編譯成java代碼來看,我們能看出用了inline的函數(shù)有兩個(gè)優(yōu)點(diǎn):一、減少函數(shù)對(duì)象的生成;二、減去方法棧的壓力(減少一次入棧和出棧)。
  2. 下面編譯成java代碼對(duì)比可以發(fā)現(xiàn),inline修飾的函數(shù)與沒有inline修飾的函數(shù)對(duì)比下,能發(fā)現(xiàn)兩個(gè)優(yōu)點(diǎn):一、創(chuàng)建一次Function對(duì)象(減少函數(shù)對(duì)象的生成);二、inline修飾的函數(shù)不是指定被調(diào)用函數(shù)去調(diào)用的,而是類似把inline修飾的函數(shù)里的內(nèi)容給copy到調(diào)用該函數(shù)的方法體里面。(減少一個(gè)入棧和出棧)。
//原Kotlin代碼
fun test() {
        val b = normalFunction(-1) {
        }
        val c = inlineFunction(0) {
        }
    }

    private fun normalFunction(a: Int, block: () -> Unit) {
        block()
        val bb = a + 3
        val cc = 3 + 5
    }

    private inline fun inlineFunction(a: Int, block: () -> Unit) {
        block()
        val bb = a + 3
        val cc = 3 + 5
    }

//編譯成java代碼
public final void test() {
      this.normalFunction(-1, (Function0)null.INSTANCE);
      Unit b = Unit.INSTANCE;
      //下面就是val c = inlineFunction(0) { } 這段kotlin代碼轉(zhuǎn)成java的執(zhí)行代碼
      int a$iv = false;
      int $i$f$inlineFunction = false;
      boolean bb$iv = false;
      bb$iv = true;
      boolean var7 = true;
      Unit c = Unit.INSTANCE;
   }

   private final void normalFunction(int a, Function0 block) {
      block.invoke();
      int bb = true;
      int cc = true;
   }

   private final void inlineFunction(int a, Function0 block) {
      int $i$f$inlineFunction = 0;
      block.invoke();
      int bb = true;
      int cc = true;
   }

何時(shí)用inline修飾符
  1. 官網(wǎng)是解釋了使用inline修飾符的函數(shù)符合兩種條件:一、你的函數(shù)接收參數(shù)中包含函數(shù)表達(dá)式。 二、你的
    函數(shù)必須短小精悍,畢竟inline是把代碼復(fù)制到調(diào)用的函數(shù)塊里,這在編譯器上也是需要時(shí)間處理的。


    編譯器警告

溫馨提示:如何從Kotlin轉(zhuǎn)成java類??雙擊你的shift鍵,輸入byte,從菜單中選擇Kotlin byteCode,在出現(xiàn)的菜單欄選擇Decompile就可以轉(zhuǎn)換成java代碼。


noinline修飾符
  1. noinline修飾符是什么?從英文上描述來看就是不內(nèi)聯(lián)的意思。從上面都可以看出內(nèi)聯(lián)實(shí)際上作用就是編譯器把內(nèi)聯(lián)函數(shù)代碼復(fù)制到調(diào)用內(nèi)聯(lián)函數(shù)的函數(shù)體里。當(dāng)我們想把內(nèi)聯(lián)函數(shù)的函數(shù)參數(shù)傳遞給其他普通函數(shù)(沒有inline修飾),這時(shí)候就需要用到我們的noinline修飾符了。

  2. 大家都明白,在java 虛擬機(jī)中,函數(shù)中傳遞參數(shù),僅是傳遞對(duì)象的引用而已。那么從上面的《從反編譯的java層分析inline修飾符》可以看到inline修飾的函數(shù)都避免創(chuàng)建新的對(duì)象了,所以這里如果希望把inline函數(shù)的函數(shù)參數(shù)傳遞給別的普通函數(shù)(沒有inline修飾),那就要用我們的主角noinline告訴inline函數(shù),這個(gè)參數(shù)是不參與內(nèi)聯(lián)的,讓參數(shù)能生成一個(gè)Function對(duì)象,把該Function對(duì)象傳遞給別的普通函數(shù)使用。
    圖一

    無法傳遞到普通函數(shù),編譯器報(bào)錯(cuò)的代碼


圖二

添加noinline修飾參數(shù)后,提示inline修飾的函數(shù)已經(jīng)多余

這里解釋圖二為什么編譯器會(huì)覺得inline修飾是多余的,希望開發(fā)人員刪除。因?yàn)閕nline修飾的函數(shù)只有一個(gè)block是函數(shù)參數(shù),唯一的函數(shù)參數(shù)都用noinline去修飾了,證明這個(gè)就是普通函數(shù),不需要用到內(nèi)聯(lián)修飾符的優(yōu)化點(diǎn)(畢竟inline是編譯器去復(fù)制,有損耗的,所以判斷是普通函數(shù)就希望開發(fā)者刪除inline和noinline,把該函數(shù)變成普通的函數(shù))。


從java層分析上面結(jié)果
  1. 代碼在上面《從反編譯的java層分析inline修飾符》可以查看,這里就簡單分析下加了noinline修飾的參數(shù)和沒加noinline修飾符在java代碼上的不同點(diǎn)。
    圖三
    沒用noinline修飾的函數(shù)參數(shù)

圖四

使用noinline修飾的函數(shù)參數(shù)

  1. 從圖三和圖四的對(duì)比可以明顯驗(yàn)證了我們的猜想,用noinline修飾后的函數(shù)參數(shù),會(huì)創(chuàng)建一個(gè)對(duì)象,并且在inline函數(shù)中把這個(gè)對(duì)象的引用傳遞給別的函數(shù)使用。

總結(jié)

Kotlin的發(fā)展真的是越來越好了,在很多方面通過語法做了優(yōu)化,官網(wǎng)都推薦用Kotlin作為開發(fā)語言了,所以我們真的要跟進(jìn)Kotlin的腳步,以至于我們不會(huì)落后太多,加油打工人??。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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