본문 바로가기

카테고리 없음

[Kotlin] Companion Object에 대하여

 

Kotlin에서 companion object를 살펴보기 위해 간단한 예시 코드를 작성해보았다.

class Example {
    companion object {
        var test = 1
    }
}

fun main() {
    val example = Example.test
}

 

위 코드를 자바 코드로 변환해 보면 다음과 같다.

public final class Example {
   private static int test = 1;
   @NotNull
   public static final Companion Companion = new Companion((DefaultConstructorMarker)null);

   public static final class Companion {
      public final int getTest() {
         return Example.test;
      }

      public final void setTest(int var1) {
         Example.test = var1;
      }

      private Companion() {
      }

      // $FF: synthetic method
      public Companion(DefaultConstructorMarker $constructor_marker) {
         this();
      }
   }
}

 

위 예시를 살펴보면 클래스에 프로퍼티를 정의 했을때

 

해당 클래스에 getter와 setter가 생성된 것과 다르게

 

backing field만 클래스의 field로서 생성되고

 

getter와 setter는 inner class인 Companion에 생성된 것을

 

확인 할 수 있다.

 

 

 

Companion object가 선언되어 있는 클래스가 불리우게 되면

 

Companion object는 초기화되며 변수와 Companion class는

 

static으로 static memory에 저장되게 된다.

 

이 중에서 main 함수가 바이트 코드로 변환된 것을 확인해 보도록 하겠다.

 

public final static main()V
   L0
    LINENUMBER 10 L0
    GETSTATIC com/example/networkmemo/Example.Companion : Lcom/example/networkmemo/Example$Companion;
    INVOKEVIRTUAL com/example/networkmemo/Example$Companion.getTest ()I
    ISTORE 0
   L1
    LINENUMBER 11 L1
    RETURN
   L2
    LOCALVARIABLE example I L1 L2 0
    MAXSTACK = 1
    MAXLOCALS = 1

 

static memory에 저장된 Companion class의 getText를 통하여

 

Example.text를 수행하고 있는 것을 확인 할 수 있다.

 

 

 

정리하자면 코틀린에서 클래스 내부에 Companion object를 통해

 

인스턴스를 선언하면  내부적으로는 field와 filed의 getter, setter를 포함한 Compnion inner class를  

 

static으로 선언하게 된다.

 

이후에는 자바 static이 사용되는 방식 그대로 사용된다고 보면 되겠다.

 

 

companion object에 메서드를 선언하지 않고 객체만을 사용하는 상황이면 

companion object {
    @JvmField
    var test = 1
}

 

이렇듯 JvmField annotation을 사용하게 되면 

public static final class Companion {
   private Companion() {
   }

   // $FF: synthetic method
   public Companion(DefaultConstructorMarker $constructor_marker) {
      this();
   }
}

 

companion object에 getter와 setter를 별도로 생성하지 않는 것을 확인 할 수 있다.