1. 람다식을 사용했을 때 무의미한 객체 생성을 예방
//1. Kotlin
fun doSomethingElse(lambda: () -> Unit) {
println("Doing something else")
lambda()
}
//1. Java
public static final void doSomethingElse(Function0 lambda) {
System.out.println("Doing something else");
lambda.invoke();
}
inline 없을 때
//2. Kotlin
fun doSomething() {
println("Before lambda")
doSomethingElse {
println("Inside lambda")
}
println("After lambda")
}
//2. Java
public static final void doSomething() {
System.out.println("Before lambda");
doSomethingElse(new Function() {
public final void invoke() {
System.out.println("Inside lambda");
}
});
System.out.println("After lambda");
}
inline 있을 때
인라인 함수를 사용하게 되면 코드는 객체를 항상 새로 만드는것이 아니라 해당 함수의 내용을 호출한 함수에 넣는 방식으로 컴파일 코드를 작성하게 됩니다.
//2. Kotlin(inline o)
inline fun doSomethingElse(lambda: () -> Unit) {
println("Doing something else")
lambda()
}
//1. Java
public static final void doSomething() {
System.out.println("Before lambda");
System.out.println("Doing something else");
System.out.println("Inside lambda");
System.out.println("After lambda");
}
==> Function 객체를 항상 호출했으나 이제는 내부에서 사용되는 2개의 함수가 내부 코드로 변환되어 사용되는것을 알 수 있었습니다. 이렇게 무의미하게 Function 객체를 항상 만들어내는 것이 없어졌습니다.
람다식에 로컬 변수 사용
//3. Kotlin
fun doSomething() {
val greetings = "Hello" // Local variable
doSomethingElse {
println("$greetings from lambda") // Variable capture
}
}
//3. Java
public static final void doSomething() {
String greetings = "Hello";
doSomethingElse(new Function(greetings) {
public final void invoke() {
System.out.println(this.$greetings + " from lambda");
}
});
}
람다식에서 사용하는 지역 변수는 아래와 같이 Function 객체의 생성자의 변수로 들어가는 것을 확인할 수 있습니다.
객체에 변수가 추가되었습니다. 즉, 객체의 메모리 사용량이 늘어났다는 것입니다.
이것을 볼때 이 경우 인라인 함수를 사용하면 좀 더 나은 성능을 보장할 수 있을 것이라는 사실을 알 수 있습니다.
2. reified 키워드
범용성 좋게 함수를 만들기 위해서 class Type을 이용할 수 있습니다. 아래와 같이 말이죠.
fun <T> doSomething(someValue: T)
하지만 이러한 class Type T 객체는 타입에 대한 정보가 런타임에서 Type Erase되어버려 알 수없어집니다. 그래서 아래와 같이 실행하면 에러가 발생하죠. 왜냐하면 타입을 알 수가 없기 때문입니다. 따라서 Class<T>를 함께 넘겨 type을 확인하고 casting 하는 과정을 거치곤합니다.
fun <T> doSomething(someValue: T, Class<T> type) { // runtime에서도 타입을 알 수 있게 Class<T> 넘김
println("Doing something with value: $someValue") // OK
println("Doing something with type: ${T::class.simpleName}") // Error
}
이러한 문제점에 때문에 reified 키워드를 사용하면 됩니다. 인라인(inline) 함수와 reified 키워드를 함께 사용하면 T type에 대해서 런타임에 접근할 수 있게 해줍니다. 따라서 타입을 유지하기 위해서 Class<T>와 같은 추가 파라미터를 넘길 필요가 없어집니다.
inline fun <reified T> doSomething(someValue: T) {
println("Doing something with value: $someValue") // OK
println("Doing something with type: ${T::class.simpleName}") // OK
}
3. inline 함수 단점
public inline 함수는 private 함수를 호출할 수 없음
아래의 코드처럼 코드를 작성하신다면 Public-API inline function cannot access non-public API fun라는 에러가 남
inline fun doSomething() {
doItPrivately() // Error
}
private fun doItPrivately() { }
'두두의 IT' 카테고리의 다른 글
[Kotlin] Infix 함수 (0) | 2022.04.12 |
---|---|
[Kotlin] 가변인자 vararg(Variable number of arguments) (0) | 2022.04.12 |
[Kotlin] data Class (0) | 2022.04.12 |
[Kotlin] Modifiers (0) | 2022.04.12 |
객체지향 프로그래밍이란? (0) | 2022.04.12 |