内联函数
内联函数消除了Lambda表达式所带来的运行时内存开销,简化编码方式
正常函数
fun main() {
val num1 = 1
val num2 = 10
val numberAdd = numberAdd(num1, num2)
println(numberAdd)
}
fun numberAdd(num1: Int, num2: Int): Int {
return num1 + num2
}
decompile后的Java代码
public final class MainKt {
public static final void main() {
int num1 = 1;
int num2 = 10;
int numberAdd = numberAdd(num1, num2);
boolean var3 = false;
System.out.println(numberAdd);
}
// $FF: synthetic method
public static void main(String[] var0) {
main();
}
public static final int numberAdd(int num1, int num2) {
return num1 + num2;
}
}
正常函数传参返回结果,方法实例正常出入栈
inline
使用inline修饰的函数
fun main() {
val num1 = 1
val num2 = 10
val numberAdd = numberAdd(num1, num2)
println(numberAdd)
}
inline fun numberAdd(num1: Int, num2: Int): Int {
return num1 + num2
}
decompile后的Java代码
public final class MainKt {
public static final void main() {
int num1 = 1;
int num2 = 10;
int $i$f$numberAdd = false;
int numberAdd = num1 + num2;
$i$f$numberAdd = false;
System.out.println(numberAdd);
}
// $FF: synthetic method
public static void main(String[] var0) {
main();
}
public static final int numberAdd(int num1, int num2) {
int $i$f$numberAdd = 0;
return num1 + num2;
}
}
用inline修饰后相当于直接把函数里面的代码拷贝过去了
fun main() {
val numberAdd = num1 + num2
println(numberAdd)
}
noinline
为什么会存在noinline关键词,先看一段代码
fun main() {
var num1 = 1
val num2 = 10
// val numberAdd = numberAdd(num1, num2)
val numberAdd = numberAdd({
num1 * 10
}, { num2 * 10 })
println(numberAdd)
}
inline fun numberAdd(block: () -> Int, block2: () -> Int): Int {
return block() + block2()
}
decompile后的Java代码
public final class MainKt {
public static final void main() {
int num1 = 1;
int num2 = 10;
int $i$f$numberAdd = false;
int var4 = false;
int var5 = num1 * 10;
var4 = false;
int var6 = num2 * 10;
int numberAdd = var5 + var6;
$i$f$numberAdd = false;
System.out.println(numberAdd);
}
// $FF: synthetic method
public static void main(String[] var0) {
main();
}
public static final int numberAdd(@NotNull Function0 block, @NotNull Function0 block2) {
int $i$f$numberAdd = 0;
Intrinsics.checkParameterIsNotNull(block, "block");
Intrinsics.checkParameterIsNotNull(block2, "block2");
return ((Number)block.invoke()).intValue() + ((Number)block2.invoke()).intValue();
}
}
当我们不需要其中一个函数内联时,可以采用noinline修饰,此时第二个函数参数就不会内联进去
fun main() {
var num1 = 1
val num2 = 10
// val numberAdd = numberAdd(num1, num2)
val numberAdd = numberAdd({
num1 * 10
}, { num2 * 10 })
println(numberAdd)
}
inline fun numberAdd(block: () -> Int,noinline block2: () -> Int): Int {
return block() + block2()
}
public final class MainKt {
public static final void main() {
int num1 = 1;
final int num2 = 10;
Function0 block2$iv = (Function0)(new Function0() {
// $FF: synthetic method
// $FF: bridge method
public Object invoke() {
return this.invoke();
}
public final int invoke() {
return num2 * 10;
}
});
int $i$f$numberAdd = false;
int var5 = false;
int numberAdd = num1 * 10 + ((Number)block2$iv.invoke()).intValue();
boolean var6 = false;
System.out.println(numberAdd);
}
// $FF: synthetic method
public static void main(String[] var0) {
main();
}
public static final int numberAdd(@NotNull Function0 block, @NotNull Function0 block2) {
int $i$f$numberAdd = 0;
Intrinsics.checkParameterIsNotNull(block, "block");
Intrinsics.checkParameterIsNotNull(block2, "block2");
return ((Number)block.invoke()).intValue() + ((Number)block2.invoke()).intValue();
}
}
crossinline
先看一段代码
fun main() {
println("开始")
printOddNum(10) {
println("函数开始")
if (it % 2 == 0) return
println("我是奇数$it")
}
println("后面还有代码要执行呢")
}
inline fun printOddNum(i: Int, block: (Int) -> Unit) {
block(i)
}
打印结果
开始
函数开始
这段代码函数的功能是打印奇数,当遇到偶数的时候,调用return,使函数结束,但是同时也导致外部函数也结束了,这样的话局部函数就影响了整个外部函数逻辑
如果我们不想局部函数影响整个函数的逻辑,我们就在方法上添加crossinline关键字修饰
inline fun printOddNum(i: Int, crossinline block: (Int) -> Unit) {
block(i)
}
这个时候调用函数,编译器就会提示我们,return@函数名 进行局部返回
fun main() {
println("开始")
printOddNum(10) {
println("函数开始")
if (it % 2 == 0) return@printOddNum
println("我是奇数$it")
}
println("后面还有代码要执行呢")
}
inline fun printOddNum(i: Int, crossinline block: (Int) -> Unit) {
block(i)
}
打印结果
开始
函数开始
后面还有代码要执行呢
这个时候就正常了