在 Kotlin 中,什么是內聯函數?有什么作用?

在 Kotlin 中,內聯函數是一種通過 inline 關鍵字聲明的函數,其主要目的是優化高階函數(即以函數作為參數或返回值的函數)的性能。

內聯函數的函數體會在編譯時直接插入到調用處,從而避免函數調用的開銷,并減少 Lambda 表達式帶來的額外內存分配。

1 基本原理

當調用一個普通函數時,程序會跳轉到函數體執行,然后返回結果。這個過程涉及棧幀的創建和銷毀,有一定的性能開銷。

普通高階函數(非內聯)示例:

fun nonInlineFun(block: () -> Unit) {block()
}fun main() {// 調用時,會生成一個 Function0 對象nonInlineFun { println("Hello") }
}

反編譯成 Java 代碼:

public final class UserKt {public static final void nonInlineFun(@NotNull Function0 block) {Intrinsics.checkNotNullParameter(block, "block");block.invoke();}public static final void main() {nonInlineFun((Function0)null.INSTANCE);}// $FF: synthetic methodpublic static void main(String[] var0) {main();}
}

內聯函數在編譯時會將函數體直接替換到調用處,避免了函數調用的開銷。

內聯函數示例:

inline fun inlineFunc(block: () -> Unit) {block()
}fun main() {// 調用時,會生成一個 Function0 對象inlineFunc { println("Hello") }
}

反編譯成 Java 代碼:

public final class UserKt {public static final void inlineFunc(@NotNull Function0 block) {int $i$f$inlineFunc = 0;Intrinsics.checkNotNullParameter(block, "block");block.invoke();}public static final void main() {int $i$f$inlineFunc = false;int var1 = false;String var2 = "Hello";System.out.println(var2);}// $FF: synthetic methodpublic static void main(String[] var0) {main();}
}

2 內聯函數的主要作用

2.1 消除高階函數的性能開銷

高階函數(如 mapfilterrun 等)通常會接收 Lambda 表達式作為參數,而 Lambda 表達式會被編譯成匿名對象(如 Function0Function1),每次調用都會創建新的對象,內聯函數通過將代碼直接插入到調用處,可以避免這種開銷。

性能對比:

  • 普通高階函數:每次調用會創建 Lambda 對象,產生內存非配和垃圾回收開銷;
  • 內聯高階函數:Lambda 代碼會直接替換到調用處,無需創建對象;
2.2 支持非局部返回(Non-local Return)

對于普通的 Lambda 表達式,return 只能返回 Lambda 自身。但內聯函數允許 Lambda 表達式中的 return 直接退出外層函數。

示例:

inline fun runInline(block: () -> Unit) {block()
}fun main() {runInline {println("執行內聯函數")return // 直接退出 main 函數}println("這行不會執行")
}
2.3 支持具體化類型參數(Reified Type Parameters)

內聯函數結合 reified 關鍵字,可以在運行時保留泛型類型信息,解決 Java 泛型類型擦除的問題。

示例:

inline fun <reified T> checkType(value: Any) {if (value is T) {println("類型匹配 ${T::class.simpleName}")}
}fun main() {checkType<String>("Kotlin") // 類型匹配 String
}

3 內聯函數的使用場景

場景說明
高頻調用的高階函數如集合操作(mapfilter)或工具函數,減少對象創建和調用開銷
需要非局部返回在 Lambda 中直接控制外層函數流程(如退出循環或函數)
類型安全的泛型操作結合 reified 實現運行時類型檢查
性能敏感代碼避免函數調用棧開銷,適用于底層庫或核心邏輯

高頻調用的高階函數(Kotlin 標準庫中的許多函數都是內聯的):

  • 集合操作函數:mapfilterforEachreduce 等;
  • 作用域函數:letrunwithapplyalso 等作用域函數;
  • 協程:launchasync 等;

另外,當需要編寫接收 Lambda 參數的高階函數時,考慮將其聲明為內聯函數。

4 內聯函數的限制和注意事項

  • 代碼膨脹: 內聯函數的代碼會被復制到每個調用處,如果函數體較大、邏輯復雜或調用頻繁,會增加生成的字節碼大小,反而影響性能;
  • 不能遞歸調用: 內聯函數無法直接遞歸(如 inline fun a() { a() }),否則會導致無限展開;
  • 部分參數可禁止內聯:使用 noinline 關鍵字禁止特定 Lambda 參數內聯;
inline fun example(block1: () -> Unit, noinline block2: () -> Unit) {}

5 總結

特性說明
性能優化減少高階函數的對象分配和調用開銷
非局部返回允許 Lambda 直接退出外層函數
具體化泛型結合 refied 保留運行時類型信息
適用場景高頻調用的小型函數、需要類型安全或控制流的場景

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/81728.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/81728.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/81728.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

LLM筆記(五)概率論

1. 隨機變量與概率分布&#xff1a;模型輸出的基礎 在LLM中&#xff0c;隨機變量最直觀的體現就是模型預測的下一個token。每個時刻&#xff0c;模型都會輸出一個概率分布&#xff0c;表示詞匯表中每個token可能是"下一個詞"的概率。 直觀理解 想象模型在處理句子…

LeetCode-滑動窗口-找到字符串中所有字母異位詞

LeetCode-滑動窗口-找到字符串中所有字母異位詞 ?? 關于專欄&#xff1a;專欄用于記錄 prepare for the coding test。 文章目錄 LeetCode-滑動窗口-找到字符串中所有字母異位詞&#x1f4dd; 找到字符串中所有字母異位詞&#x1f3af;題目描述&#x1f50d; 輸入輸出示例&am…

PostgreSQL 初體驗

目錄 一、PostgreSQL 1. 簡介 2. 特點 &#xff08;1&#xff09; 開源免費&#xff08;Open Source&#xff09; &#xff08;2&#xff09;標準兼容&#xff08;SQL Compliance&#xff09; &#xff08;3&#xff09; 豐富的數據類型&#xff08;Data Types&#xff09…

05_核支持向量機

描述 核支持向量機&#xff08;通常簡稱為SVM&#xff09;可以推廣到更復雜模型的擴展&#xff0c;這些模型無法被輸入空間的超平面定義。 SVM 的核心思想是找到一個最優的超平面&#xff0c;將不同類別的數據分開。這個超平面不僅要能夠正確分類數據&#xff0c;還要使得兩個…

Java + 鴻蒙雙引擎:ZKmall開源商城如何定義下一代B2C商城技術標準?

在 B2C 電商領域持續革新的當下&#xff0c;技術架構的優劣成為決定商城競爭力的核心要素。ZKmall開源商城以其創新融合的 Java 與鴻蒙雙引擎&#xff0c;為下一代 B2C 商城技術標準勾勒出全新藍圖&#xff0c;在性能、兼容性、拓展性等關鍵維度實現了重大突破。 一、Java 技術…

關于 Web 漏洞原理與利用:3. CSRF(跨站請求偽造)

一、原理&#xff1a; 利用用戶登錄態偽造操作 CSRF&#xff08;Cross-Site Request Forgery&#xff0c;跨站請求偽造&#xff09;是攻擊者“借刀殺人”&#xff0c;借用用戶瀏覽器中已有的登錄狀態&#xff0c;誘導用戶完成攻擊者指定的操作。 1. 基本機制分解 1&#xf…

【HTML5】【AJAX的幾種封裝方法詳解】

【HTML5】【AJAX的幾種封裝方法詳解】 AJAX (Asynchronous JavaScript and XML) 封裝是為了簡化重復的異步請求代碼&#xff0c;提高開發效率和代碼復用性。下面我將介紹幾種常見的 AJAX 封裝方式。 方法1. 基于原生 XMLHttpRequest 的封裝 XMLHttpRequest。其主要特點如下…

C++ - 網絡編程之初始連接(Winsock2 概述、初始連接案例、初始連接案例解讀)

一、Winsock2 概述 Winsock2&#xff08;Windows Sockets 2&#xff09;是微軟提供的 Windows 平臺網絡編程庫 二、初始連接案例 1、Server #include <winsock2.h> #include <ws2tcpip.h> #include <iostream>#pragma comment(lib, "ws2_32.lib&quo…

Spring Cloud Gateway深度解析:原理、架構與生產實踐

文章目錄 前言一、概述二、核心架構設計及設計原理2.1 分層架構模型網絡層&#xff08;I/O模型&#xff09;核心處理層 2.2 核心組件協作流程路由定位階段過濾器執行階段 2.3 響應式編程模型實現Reactor上下文傳遞背壓處理機制 2.4 動態路由設計原理2.5 異常處理體系2.6 關鍵路…

游戲開發實戰(一):Python復刻「崩壞星穹鐵道」嗷嗚嗷嗚事務所---源碼級解析該小游戲背后的算法與設計模式【純原創】

文章目錄 奇美拉項目游戲規則奇美拉(Chimeras)檔案領隊成員 結果展示&#xff1a; 奇美拉項目 由于項目工程較大&#xff0c;并且我打算把我的思考過程和實現過程中踩過的坑都分享一下&#xff0c;因此會分3-4篇博文詳細講解本項目。本文首先介紹下游戲規則并給出奇美拉檔案。…

說一下響應狀態碼有哪些?

HTTP響應狀態碼分類(RFC 7231標準) 1. 1xx(信息類) 臨時響應,表示請求已被接收,需要繼續處理 100 Continue:客戶端應繼續發送請求體 101 Switching Protocols:服務器同意升級協議(如WebSocket) 102 Processing(WebDAV):服務器正在處理但未完成 2. 2xx(成功類)…

Linux多進程 寫時拷貝 物理地址和邏輯地址

如果不采用寫時拷貝技術 直接fork子進程 會發生什么&#xff1f; 如上圖所示 橙色為父進程所占內存空間 綠色為子進程所占內存空間。 如果子進程只是需要做出一點點和父進程不一樣的 其余和父進程均為相同 第一 就會出現復制開銷比較大&#xff1b;第二占用內存空間 所以 …

【TTS回顧】Bert-VITS2深度解析:融合BERT的多語言語音合成模型

一、基本介紹 Bert-VITS2是基于VITS(Variational Inference with adversarial learning for end-to-end Text-to-Speech)的改進版本,通過整合BERT語義編碼能力,顯著提升了語音合成的自然度和表現力。項目地址:https://github.com/fishaudio/Bert-VITS2 語種自然度相似度流…

win11下docker 的使用方案

Windows 11 Docker 使用方式對比 特性Docker Desktop (使用 WSL 2 后端)直接在 WSL 2 中安裝 Docker Engine安裝與易用性極簡&#xff0c;一鍵安裝&#xff0c;提供直觀的 GUI 界面 管理容器、鏡像、卷等相對復雜&#xff0c;需手動在 Linux 環境中安裝 Docker Daemon 并配置G…

配合本專欄前端文章對應的后端文章——從模擬到展示:一步步搭建傳感器數據交互系統

對應文章&#xff1a;進一步完善前端框架搭建及vue-konva依賴的使用&#xff08;Vscode&#xff09;-CSDN博客 目錄 一、后端開發 1.模擬傳感器數據 2.前端頁面呈現數據后端互通 2.1更新模擬傳感器數據程序&#xff08;多次請求&#xff09; 2.2&#x1f9e9; 功能目標 …

牛客網NC209794:使徒襲來

牛客網NC209794:使徒襲來 題目背景 問題分析 數學建模 設三位駕駛員的戰斗力分別為 a, b, c已知條件&#xff1a;a b c n (n為輸入的正整數)目標&#xff1a;求 a b c 的最小值 解題思路 根據算術-幾何平均值不等式(AM-GM不等式)&#xff0c;對于任意正實數a, b, c&a…

動態規劃之爬樓梯模型

文章目錄 爬樓梯模型LeetCode 746. 使用最小花費爬樓梯思路Golang 代碼 LeetCode 377. 組合總和 Ⅳ思路Golang 代碼 LeetCode 2466. 統計構造好字符串的方案數思路Golang 代碼 LeetCode 2266. 統計打字方案數思路Golang 代碼 爬樓梯模型 爬樓梯模型是動態規劃當中的一個經典模型…

【每天一個知識點】湖倉一體(Data Lakehouse)

“湖倉一體”&#xff08;Data Lakehouse&#xff09;是一種融合了數據湖&#xff08;Data Lake&#xff09;與數據倉庫&#xff08;Data Warehouse&#xff09;優勢的新型數據架構。它既繼承了數據湖對多類型數據的靈活存儲能力&#xff0c;也具備數據倉庫對結構化數據的高效查…

Linux | mdadm 創建軟 RAID

注&#xff1a;本文為 “Linux mdadm RAID” 相關文章合輯。 略作重排&#xff0c;未整理去重。 如有內容異常&#xff0c;請看原文。 Linux 下用 mdadm 創建軟 RAID 以及避坑 喵??&#xfecc;?? Oct 31, 2023 前言 linux 下組軟 raid 用 mdadm 命令&#xff0c;multi…

Unity自定義shader打包SpriteAtlas圖集問題

Unity打包圖集還是有一些坑的&#xff0c;至于圖集SpriteAtlas是什么請參考我之前寫的文章&#xff1a;【Sprite Atlas】Unity新圖集系統SpriteAtlas超詳細使用教程_spriteatlas 使用-CSDN博客 問題&#xff1a; 今天碰到的問題是&#xff0c;shader繪制的時候&#xff0c;因…