【轉】Kotlin的inline內聯函數


原文鏈接:https://blog.csdn.net/Jaden_hool/article/details/78437947

方法調用流程

調用一個方法是一個壓棧和出棧的過程,調用方法時將棧針壓入方法棧,然后執行方法體,方法結束時將棧針出棧,這個壓棧和出棧的過程會耗費資源,這個過程中傳遞形參也會耗費資源。

為什么需要inline?

有些簡單的方法會被頻繁調用,什么叫簡單的方法呢,舉個例子:

fun <T> check(lock: Lock, body: () -> T): T {
        lock.lock()
        try {
            return body()
        } finally {
            lock.unlock()
        }
    }

這個check方法的方法體中,不會將它的形參再傳遞給其他方法。我們調用一下 check 方法:

  check(l, {"我是lambda方法體"})//l是一個Lock對象

對於編譯器來說,調用 check 方法就要將參數l和 lambda 表達式 {"我是 lambda方法體"} 進行傳遞,還要將 check 方法進行壓棧出棧處理,這個過程就會耗費資源。

如果我們把 check 方法刪除,直接執行 check 方法的方法體:

        l.lock()
        try {
            return "我是lambda方法體"
        } finally {
            l.unlock()
        }

這樣做的效果和調用 check方法是一樣的,而且不需要壓棧出棧了,但是代碼是寫給人看的,這樣寫明顯產生了代碼壞味道,老司機會告訴你,這幾行代碼需要抽成一個方法,避免多處調用產生冗余代碼。於是你就老老實實把這幾行代碼抽成了 check方法,那么如上所述,一旦這個方法被頻繁調用,壓棧出棧將會帶來性能問題。針對這個問題,kotlin 引入了 inline 關鍵字。我們在 check 方法前加上 inline關鍵字:

inline fun <T> check(lock: Lock, body: () -> T): T {
        lock.lock()
        try {
            return body()
        } finally {
            lock.unlock()
        }
    }

然后我們再調用 check 方法,編譯器就會在編譯期幫我們進行優化:
將我們寫的代碼

  check(l, {"我是lambda方法體"})//l是一個Lock對象

換成

        l.lock()
        try {
            return "我是lambda方法體"
        } finally {
            l.unlock()
        }

也就是說 inline 關鍵字實際上增加了代碼量,但是提升了性能,而且增加的代碼量是在編譯期執行的,對程序可讀性不會造成影響。

其它

如果 check 方法中的參數需要傳遞給其他非 inline 方法:

inline fun <T> check(lock: Lock, body: () -> T): T {
            lock.lock()
            try {
                otherCheck(body)//會報錯
                return body()
            } finally {
                lock.unlock()
            }
    }

    fun <T> otherCheck(body: ()-> T){

    }

那么調用 otherCheck 是會報錯的,因為 check 方法中的形參 body 現在已經 inline 了,不是一個函數對象了,也就不能作為一個參數傳遞了,除非在 body 參數前加上 noinline 關鍵字。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM