본문 바로가기

Develop/Kotlin

backingField와 recursive call

728x90

Backing field

class User(name: String) {
    var name: String = name
        get() = name
        set(value) {name = value}

}

위와 같은 클래스가 있다고 할 때, 코틀린에서 해당 property를 get 혹은 set 할 때 재귀호출이 일어나게 된다.

public fun main(){
  println(User("mj").name)
    User("mj").name = "jyami"
}

위와 같이 name 프로퍼티를 접근하는 것이 getter를 부르는 것과 같기 때문에
결국get() = this.get() 과 같이, getter를 부르면서 다시 getter를 호출하는 것과 같다.

마찬가지로 name 프로퍼티를 할당하는 것도 setter를 부르는 것과 같아서. set()=this.set("jyami") 다시 setter를 호출하게 된다.

따라서 getter, setter 모두 본인의 필드를 참조하는 경우에는 StackOverflowException 을 발생시키게 된다. 친절하게도 intellij 에서는 recursive call 이라고 안내를 해주고 있다.

추가로 kotlin을 kotlinc를 사용하여 생성된 바이트코드를 보면 어떤 경우에 backing field가 생성되는지를 볼 수 있다. 즉 backing field가 인스턴스 변수로 생성되는 경우는 아래와 같다.

  • 하나이상의 기본 접근자를 사용하는 경우 (getter, setter)
  • 커스텀하게 만든 접근자에서 field 를 사용하는 경우.
data class HttpResponse(val body: String, var headers: Map<String, String>) {

    val hasBody: Boolean
        get() = body.isNotBlank()

    var statusCode: Int = 100
        set(value) {
            if (value in 100..599) field = value
        }
}

body, header는 기본 접근자를 이유로, statusCode는 커스텀 접근자를 이유로 생성되는데, hasBody는 그렇지 않다. (필드로 생성되지 않는다.)


javap -c -p com.kakao.talk.HttpResponse       

 Compiled from "BackingField.kt"

public final class com.jyami.HttpResponse {
  private final java.lang.String body;
  private java.util.Map<java.lang.String, java.lang.String> headers;
  private int statusCode;

  // 함수들의 어셈블러 코드

'Develop > Kotlin' 카테고리의 다른 글

Kotlin Void vs Unit vs Nothing  (0) 2022.05.02
Ktor 찍먹하기 - 간단 HTTP API 작성  (1) 2021.12.11