inline
- 為了解決每次調(diào)用高階函數(shù)時(shí)給它傳遞lambda表達(dá)式時(shí)會(huì)創(chuàng)建匿名內(nèi)部類引入了inline關(guān)鍵字
- inline修飾的函數(shù),不僅會(huì)把函數(shù)體的內(nèi)容進(jìn)行復(fù)制鋪平藻烤,還會(huì)把函數(shù)類型參數(shù)的內(nèi)容復(fù)制鋪平绷雏;
- 減少一次函數(shù)調(diào)用头滔,少創(chuàng)建了一個(gè)匿名內(nèi)部類;
- inline修飾的高階函數(shù)中不能調(diào)用私有方法(這個(gè)是確定的)
- 如果內(nèi)聯(lián)函數(shù)是internal那么它內(nèi)部就能調(diào)用internal修飾的普通函數(shù)涎显;
inline fun performOperation(a: Int, b: Int, crossinline operation: (Int, Int) -> Int): Int {
return operation(a, b)
}
fun performMain() {
performOperation(1, 2) { a, b ->
a + b
}
}
public static final int performOperation(int a, int b, @NotNull Function2 operation) {
int $i$f$performOperation = 0;
Intrinsics.checkNotNullParameter(operation, "operation");
return ((Number)operation.invoke(a, b)).intValue();
}
public static final void performMain() {
byte a$iv = 1;
int b$iv = 2;
int $i$f$performOperation = false;
int var5 = false;
int var10000 = a$iv + b$iv;
}
noinline
- 當(dāng)在內(nèi)聯(lián)函數(shù)中想把某個(gè)函數(shù)類型的參數(shù)進(jìn)行傳遞或者返回坤检,這時(shí)就不能把這個(gè)參數(shù)鋪平,所以引入了noinline關(guān)鍵字
return與inline之間的約定
- 在非inline函數(shù)中期吓,return無(wú)法使用(必須使用return@xxx 指明返回的函數(shù))早歇,只有在inline函數(shù)中可以使用return語(yǔ)句這樣就不會(huì)有異議;
inline fun inlineFunction(block: () -> Unit) {
println("Before inline")
block()
println("After inline")
}
fun main() {
println("Start")
inlineFunction {
println("Inside inline")
return // 非局部返回讨勤,從 main 函數(shù)返回
}
println("End")
}
crossinline
- crossinline是告訴IDE箭跳,lambda表達(dá)式的局部不能使用return
inline fun performOperation(a: Int, b: Int, crossinline operation: (Int, Int) -> Unit) {
operation(a, b)
}
fun performMain() {
performOperation(1, 2) { a, b ->
a + b
// 此處使用 return 語(yǔ)句來(lái)中斷代碼執(zhí)行是不被允許的,因?yàn)閏rossinline關(guān)鍵字的作用
}
Log.d("TAG", "performMain: ")
}
JMH 測(cè)試 inline
調(diào)用一次
嵌套調(diào)用10次
@BenchmarkMode(Mode.Throughput)
@Warmup(iterations = 3)
@Measurement(iterations = 5, time = 2, timeUnit = TimeUnit.SECONDS)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
open class InlineBenchmark {
private fun foo(block: () -> Unit) {
block()
}
private inline fun fooInline(block: () -> Unit) {
block()
}
@Benchmark
fun testNoInline() {
var i = 0
foo {
foo {
foo {
foo {
foo {
foo {
foo {
foo {
foo {
foo {
i++
}
}
}
}
}
}
}
}
}
}
}
@Benchmark
fun testInline() {
var i = 0
fooInline {
fooInline {
fooInline {
fooInline {
fooInline {
fooInline {
fooInline {
fooInline {
fooInline {
fooInline {
i++
}
}
}
}
}
}
}
}
}
}
}
}
fun main() {
val options = OptionsBuilder()
.include(InlineBenchmark::class.java.simpleName)
.resultFormat(ResultFormatType.JSON)
.build()
Runner(options).run()
}
可以看到當(dāng)處于嵌套多次調(diào)用時(shí)潭千,使用inline關(guān)鍵字的性能要遠(yuǎn)好于noinline