함수 타입 파라리터를 갖는 함수에 inline 한정자를 붙여라
inline의 역할은 컴파일 시점에 '함수를 호출하는 부분'을 '함수의 본문'으로 대체하는 역할을 한다.
inline fun repeat(times: Int, action: (Int) -> Unit) {
for (index in 0 until times) {
action(index)
}
}
repeat(10) {
print (it)
}
위의 repeat
는 컴파일 시점에 아래와 같이 교체된다.
for (index in 0 until times) {
print(index)
}
inline을 사용하면 다음과 같은 장점이 있다.
- reified를 사용할 수 있다.
- 더욱 빠르게 동작한다.
- 비지역(non-local) 리턴을 사용할 수 있다.
reified를 사용할 수 있다.
구버전의 Java는 Generic이 없었다. 그래서 JVM 바이트 코드에는 아직도 Generic이 없다. 즉, 컴파일 시 Generic에 대한 정보가 지워진다. 예를들어 List<Int>가 컴파일되면 List이다.
any is List<*> 오류
fun <T>.printTypeName() {
print(T::class.simpleName) //오류
}
함수를 inline으로 사용하면 이러한 제한을 무시할 수 있다.
inline fun <reified T>.printTypeName() {
print(T::class.simpleName)
}
printTypeName<Int>() //Int
컴파일하는 동안 위 코드는 아래로 대체된다.
print(Int::class.simpleName)
더욱 빠르게 동작한다.
함수 호출과 리턴을 위해 jump를 수행하는 과정과 back stack을 추적하는 과정이 없기 때문이다. 함수를 파라미터로 갖지 않는 경우에는 큰 차이가 없다. 앞서 서술한 과정이 없기 때문이다.
그리고, 함수는 일급 객체이다. 함수는 컴파일 시 클래스로 컴파일 된다.
val lambda: () -> Unit = {
...
}
class Test$lambda implements Function0<Unit> {
Unit invoke() {
...
}
}
Function0<Unit> lambda = new Function0<Unit>() {
...
}
앞선 포스팅에서 '불필요한 객체 생성을 피하라'의 원칙에 따르면 효율성 측면에서도 좋지 않다.
비지역적(non-local) 리턴을 사용할 수 있다.
fun repeatNoInline(times: Int, action: (Int) -> Unit) {
for (index in 0 until times) {
action(index)
}
}
위의 함수는 내부에서 return을 사용할 수 없다.
repeatNoInline(10) {
print(it)
return // 오류
}
이는 함수가 컴파일될 때 객체로 래핑되어서 발생하기 때문이다.
inline fun repeatNoInline(times: Int, action: (Int) -> Unit) {
for (index in 0 until times) {
action(index)
}
}
repeat(10) {
print(it)
}
반면에 inline을 사용하면 위처럼 사용할 수 있다.
inline의 문제점
- 가시성 제한이 있을 경우 사용할 수 없다.
- 재귀적으로 동작할 수 없다.
inline이 inline을 호출하는 경우를 유의해야 한다.
crossinline과 noinline
함수는 인라인으로 만들고 파라미터로 받는 함수는 인라인으로 받고 싶지 않은 경우가 있다. 이럴 때 crossinline/noinline을 사용할 수 있다.
- crossinline: 파라미터로 인라인 함수를 받지만, 비지역적 리턴을 하는 함수는 받을 수 없다.
- noinline: 인라인 함수를 받을 수 없다.
crossinline/noinline은 IntelliJ가 적절히 추천해주므로 추상적으로 알고 있어도 된다.
'안드로이드 > Kotlin' 카테고리의 다른 글
8. Effective Kotlin - 사용하지 않는 객체의 레퍼런스를 제거하라 (0) | 2022.04.01 |
---|---|
7. Effective Kotlin - 인라인 클래스의 사용을 고려하라. (0) | 2022.04.01 |
5. Effective Kotlin - 효율성 (0) | 2022.03.20 |
4. Effective Kotlin - 가독성 (0) | 2022.03.19 |
3. Effective Kotlin - 결과 부족 시 null & Failure를 사용하라 (0) | 2022.03.17 |