@JvmStatic

요약 : Kotlin에서 Companion object에 있는 변수, 함수를 Companion 이름 없이 클래스 이름만으로 접근할 수 있다. 이것을 자바에서도 가능하도록 컴파일 과정에서 변환해주는 어노테이션이다. 단, 자바에서 변수는 getXxx, setXxx와 같은 함수로 접근해야 한다.

아래와 같은 Kotlin 코드가 있다.

class SomeThing() {
    companion object {
        fun sayHi() {
            println("hello")
        }
    }
}

이 코드를 자바에서 아래와 같이 호출할 수 있다.

public class main {
    public static void main(String[] args) {
        SomeThing.Companion.sayHi();
    }
}

JvmStatic을 붙이면 Companion object 없이 sayHi 함수를 호출할 수 있다.

// Kotlin
class SomeThing() {
    companion object {
        @JvmStatic
        fun sayHi() {
            println("hello")
        }
    }
}

// Java
public class main {
    public static void main(String[] args) {
        SomeThing.sayHi();
    }
}

Kotlin 코드의 디컴파일 된 부분 차이를 알아보자. JvmStatic이 붙지 않으면 아래와 같다.

public final class SomeThing {
   @NotNull
   public static final Companion Companion = new Companion((DefaultConstructorMarker)null);

   @Metadata(
      mv = {1, 9, 0},
      k = 1,
      d1 = {"\\u0000\\u0012\\n\\u0002\\u0018\\u0002\\n\\u0002\\u0010\\u0000\\n\\u0002\\b\\u0002\\n\\u0002\\u0010\\u0002\\n\\u0000\\b\\u0086\\u0003\\u0018\\u00002\\u00020\\u0001B\\u0007\\b\\u0002¢\\u0006\\u0002\\u0010\\u0002J\\u0006\\u0010\\u0003\\u001a\\u00020\\u0004¨\\u0006\\u0005"},
      d2 = {"LSomeThing$Companion;", "", "()V", "sayHi", "", "kotlinStudy"}
   )
   public static final class Companion {
      public final void sayHi() {
         String var1 = "hello";
         System.out.println(var1);
      }

      private Companion() {
      }

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

JvmStatic이 붙으면 아래와 같다. SomeThing 클래스에 이전에 없던 static 함수 sayHi가 생성됐다.

public final class SomeThing {
   @NotNull
   public static final Companion Companion = new Companion((DefaultConstructorMarker)null);

   @JvmStatic
   public static final void sayHi() {
      Companion.sayHi();
   }

   @Metadata(
      mv = {1, 9, 0},
      k = 1,
      d1 = {"\\u0000\\u0012\\n\\u0002\\u0018\\u0002\\n\\u0002\\u0010\\u0000\\n\\u0002\\b\\u0002\\n\\u0002\\u0010\\u0002\\n\\u0000\\b\\u0086\\u0003\\u0018\\u00002\\u00020\\u0001B\\u0007\\b\\u0002¢\\u0006\\u0002\\u0010\\u0002J\\b\\u0010\\u0003\\u001a\\u00020\\u0004H\\u0007¨\\u0006\\u0005"},
      d2 = {"LSomeThing$Companion;", "", "()V", "sayHi", "", "kotlinStudy"}
   )
   public static final class Companion {
      @JvmStatic
      public final void sayHi() {
         String var1 = "hello";
         System.out.println(var1);
      }

      private Companion() {
      }

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

변수에 대해서도 알아보자. Kotlin Companion object에 name 이라는 변수가 있다.

class SomeThing() {
    companion object {
        val name = "android"
    }
}

// Java
public class main {
    public static void main(String[] args) {
        SomeThing.Companion.getName();
    }
}

코틀린 코드를 디컴파일하면 아래와 같다.