Companion Object vs Inner Object
들어가며
companon object를 단순히 java의 static을 대체한다고만 하는 경우가 많아 좀 더 자세히 알아보도록 하자.
companon object 에 대한 정의는 공식 문서에서 확인할 수 있다.
공식문서에서는 원리보다는 용례에 대해 중점적으로 설명하고 있는데, 여기에서는 companon object의 원리와 inner object와의 차이에 대해서 알아보고자 한다.
예시코드
class CompanionObject {
companion object{
const val LIMIT=100
fun add(a: Int,b: Int): Int = a+b
}
}
class InnerObject {
object Companion{
const val LIMIT=100
fun add(a: Int,b: Int): Int = a+b
}
}
분석
바이트 코드를 살펴보면 static inner 클래스가 생성되는 것은 동일하지만, 인스턴스 선언방식과 상수의 위치 차이를 알 수 있다.
// CompanionObject.java
public final class CompanionObject {
public static final int LIMIT = 100;
@NotNull
public static final Companion Companion = new Companion((DefaultConstructorMarker)null);
public static final class Companion {
public final int add(int a, int b) {
return a + b;
}
private Companion() {
}
// $FF: synthetic method
public Companion(DefaultConstructorMarker $constructor_marker) {
this();
}
}
}
// InnerObject.java
public final class InnerObject {
public static final class Companion {
public static final int LIMIT = 100;
@NotNull
public static final Companion INSTANCE;
public final int add(int a, int b) {
return a + b;
}
private Companion() {
}
static {
Companion var0 = new Companion();
INSTANCE = var0;
}
}
}
자바에서 코틀린 companion object 호출
바이트 코드를 보면 알 수 있듯, 함수는 Companion 클래스 내부에 선언되어 있으므로 직접 호출이 불가능하다.
호출을 하려면 Companion 클래스까지 정의를 해야하는데 이는 java static 메서드의 정의와 상이하다.
import com.example.kotlinspring.companionobject.CompanionObject;
public class CompanionJavaTest {
public static void main(String[] args) {
int result = CompanionObject.add(1, 2); // 에러 발생
int result = CompanionObject.Companion.add(1,2);
}
}
직접 호출을 하기 위해서는 @JVMStatic
어노테이션을 코틀린에서 정의하면 된다.
class CompanionObject {
companion object : Factory<CompanionObject>{
const val LIMIT=100
@JvmStatic fun add(a: Int,b: Int): Int = a+b
override fun create(): CompanionObject = CompanionObject()
}
}
이렇게 하면 아래처럼 바이트 코드에 static 함수가 생기고 이 함수는 Companion 클래스의 함수를 다시 호출한다.
public final class CompanionObject {
public static final int LIMIT = 100;
@NotNull
public static final Companion Companion = new Companion((DefaultConstructorMarker) null);
@JvmStatic
public static final int add(int a, int b) {
return Companion.add(a, b);
}
//중략...
}