코틀린에서는 Class의 내부가 아닌, 소스 파일의 최상위 수준(모든 다른 클래스의 밖)에 함수와 프로퍼티를 선언할 수 있다.
(자바의 경우 모든 함수와 프로퍼티는 무조건 클래스 내부에 선언되어야 한다.)
소스 파일(클래스 내부X)에 함수를 선언하면 최상위 함수가 된다. 심지어 자바 파일에서 해당 함수를 호출하는 것 역시 가능하다. 어떻게 이것이 가능한 걸까?
코틀린 코드를 자바 코드로 디컴파일해서 확인해보면 이유를 알 수 있다.
// testFunction.kt
package testPackage
fun testFunction() = println("test")
// Decompile to Java
public final class TestFunctionKt {
public static final void testFunction() {
String var0 = "test";
System.out.println(var0);
}
}
코틀린 파일 이름을 클래스명으로한 클래스가 생성되는 것을 확인할 수 있다. 코틀린은 개발자의 편의를 위해 스스로 클래스를 선언하고 정적 메서드를 생성했던 것이다.
따라서 코틀린으로 최상위 함수로 선언한 함수를 자바 코드에서 해당 파일 명의 클래스로 호출할 수 있다.
import testPackage.TestFunctionKt;
...
TestFunctionKt.testFunction();
파일에 @JvmName
어노테이션을 추가하여 자동으로 생성되는 클래스 명을 지정할 수 있다.
⇒ 어노테이션은 파일의 맨 앞, 패키지 이름 선언 이전에 위치해야 함
@file:JvmName(Tf)
package testPackage
fun testFunction() = println("test")
// Java에서 호출
import testPackage.Tf;
...
Tf.testFunction();
함수와 만찬가지로 프로퍼티도 파일의 최상위 수준에 놓을 수 있다.
// testFunction.kt
const val first = "first"
val second = "second"
var third = "third"
// Decompile to Java
public final class TestFunctionKt {
@NotNull
public static final String first = "first";
@NotNull
private static final String second = "second";
@NotNull
private static String third = "third";
@NotNull
public static final String getSecond() {
return second;
}
@NotNull
public static final String getThird() {
return third;
}
public static final void setThird(@NotNull String var0) {
Intrinsics.checkNotNullParameter(var0, "<set-?>");
third = var0;
}
}
최상위 함수와 동일하게 프로퍼티가 선언된 파일 명으로 클래스가 선언되고 내부의 정적 필드로 선언 되었다.