[IntelliJ] Kotlin to Java 디컴파일
kotlin 스펙에는 문제가 없으나 java 컴파일 과정에서 문제가 있는 경우가 있다. 예를 들면 제네릭의 경우 Type erasure 때문에 함수명 등이 겹칠 수 있다. 이런 경우 IntelliJ에서 디컴파일을 해보면 문제를 파악하기 쉽다.
fun List<Int>.avg(): Double = this.sum().toDouble() / this.size
fun List<Double>.avg(): Double = this.sum().toDouble() / this.size
fun main() {
val l1 = listOf(1, 2, 3)
val l2 = listOf(1.0, 2.0, 5.0)
println(l1.avg())
println(l2.avg())
}
예를 들어 위 코틀린 코드를 컴파일하면
Platform declaration clash: The following declarations have the same JVM signature (avg(Ljava/util/List;)D):
위처럼 자바에서 함수 시그니처가 겹친다는 에러가 나오게 된다.
import java.util.List;
import kotlin.Metadata;
import kotlin.collections.CollectionsKt;
import org.jetbrains.annotations.NotNull;
@Metadata(
mv = {1, 6, 0},
k = 2,
d1 = {"..."},
d2 = {"main", "", "avg", "", "", "", "kotlin-temp"}
)
public final class MainKt {
public static final double avg(@NotNull List param0) {
// $FF: Couldn't be decompiled
}
public static final double avg(@NotNull List param0) {
// $FF: Couldn't be decompiled
}
public static final void main() {
List l1 = CollectionsKt.listOf(new Integer[]{1, 2, 3});
List l2 = CollectionsKt.listOf(new Double[]{1.0, 2.0, 5.0});
double var2 = avg(l1);
System.out.println(var2);
var2 = avg(l2);
System.out.println(var2);
}
// $FF: synthetic method
public static void main(String[] var0) {
main();
}
}
디컴파일을 해보면 이렇게 나오고, 왜 컴파일이 안되는지 직관적으로 알 수 있다
(위 예시의 경우엔, 함수에 @JvmName
을 붙여야 한다)
IntelliJ Kotlin Bytecode 디컴파일 방법
Tools - Kotlin - Show Kotlin Bytecode 클릭
그럼 오른쪽에 이렇게 Kotlin Bytecode가 나오고, Decompile을 누르면 Java 버전의 코드로 변환된다.