You can think of inline functions as a copy/paste instruction for the compiler. Each time the compiler sees a call to a function marked with inline, it will replace the call with the concrete function body.
It makes sense to use the inline function only if it's a higher-order function that receives a lambda as one of its arguments:
inline fun doesntMakeSense(something: String) {
println(something)
}
This is the most common use case where you would like to use inline:
inline fun makesSense(block: () -> String) {
println("Before")
println(block())
println("After")
}
You call it as usual, with the block body:
makesSense {
"Inlining"
}
But if you view the bytecode, you'll see it's actually translated to the lines produces and not to a function call:
println("Before")
println("Inlining")
println("After")
In the actual code, you'll see the following:
String var1 = "Before"; <- Inline function call
System.out.println(var1);
var1 = "Inlining";
System.out.println(var1);
var1 = "After";
System.out.println(var1);
var1 = "Before"; // <- Usual code
System.out.println(var1);
var1 = "Inlining";
System.out.println(var1);
var1 = "After";
System.out.println(var1);
Notice there's absolutely no difference between the two blocks.
Since the inline function is copy/paste, you shouldn't use it if you have more than a few lines of code. It would be more efficient to have it as a regular function.