Kotlin의 범위함수 apply에 대해 공부하면서 예제코드를 작성할 때였다.
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
applyFunction()
}
inner class Person(){
var name: String?= null
var age: Int? = null
fun getName(): String?{
return name
}
}
private fun applyFunction(){
val person = Person().apply{
name = "ApplyTest"
age = 1
}.getName()
Log.d("Glion", person?: "Null")
}
applyFunction() 호출 시 범위함수 apply를 사용하여 person 객체의 속성을 변경하고, getName을 호출하여 person 변수에 name이 저장되게끔 하였다. 그리고 로그를 찍어 확인해보려고 했으나
Platform declaration clash: The following declarations have the same JVM signature
fun `<get-name>`(): String? defined in com.example.oddmentsproject.activity.MainActivity.Person
fun getName(): String? defined in com.example.oddmentsproject.activity.MainActivity.Person
와 같은 오류가 나타났다.
구글링을 해보니,
<get-name>() 과 getName이 같은 JVM signature를 가지고 있다는 것이다.
코틀린코드가 컴파일 될때 자바 바이트코드로 변경되는데 이때 이 JVM signature가 동일하기 때문에 오류가 난다고 한다.
내가 짠 코드에서 getName 함수는 하나뿐인데 이게 무슨소리지??
같은 JVM signature를 가지고 있다고 하는데, 무슨말인지 모르겠고 로그를 보면 Person 클래스에 getName() 과
'<get-name>' 이 중복되었다고 하고, 바이트 코드로 변경될때 동일한게 있어 오류가 난다고 했으니 위 코드를 자바 바이트 코드로 디컴파일해서 살펴보자.
private final void applyFunction() {
Person var2 = new Person();
int var4 = false;
var2.setName("ApplyTest");
var2.setAge(1);
String person = var2.getName();
String var10001 = person;
if (person == null) {
var10001 = "Null";
}
Log.d("Glion", var10001);
}
public final class Person {
@Nullable
private String name;
@Nullable
private Integer age;
@Nullable
public final String getName() { // 이부분과
return this.name;
}
public final void setName(@Nullable String var1) {
this.name = var1;
}
@Nullable
public final Integer getAge() {
return this.age;
}
public final void setAge(@Nullable Integer var1) {
this.age = var1;
}
@Nullable
public final String getName() { // 이부분이 동일하다
return this.name;
}
}
이 코드는 위의 Person 클래스 생성부분과 applyFunction() 함수 부분을 디컴파일 한 코드이다.
Person 클래스 생성부분을 보면, 멤버변수 name과 age가 private으로 선언되어 있고, 이를 접근하기 위한 getter, setter 가 생성되어 있고, 동일한 getName() 메소드가 정의되어있는걸 확인 할 수 있다.
즉, 동일한 함수가 2개 생성되어 컴파일 오류가 난 것이다.
해결방법은 2가지이다.
1. 자동생성되는 getter, setter 의 이름인 "get/set + 변수명" 과 다른 함수를 작성한다.
2. @JvmName 을 달아준다.
1번은 간단하게 함수명을 다른걸로 바꾸면 해결된다. getName() 만 피하면 되니까...
뭐 가령 getObjName()으로 변경만 해도 문제없이 실행된다.
2번은 중복된 JVM signature를 변경해주는 것이다. 내가 생성한 getName() 함수 위에 다음과 같이 추가해주면 된다.
inner class Person(){
var name: String?= null
var age: Int? = null
@JvmName("userDefinedGetName")
fun getName(): String?{
return name
}
}
@JvmName을 사용하여 userDefinedGetName으로 JVM Signature를 변경해주었다. 디컴파일하면 다음과 같다.
public final class Person {
@Nullable
private String name;
@Nullable
private Integer age;
@Nullable
public final String getName() {
return this.name;
}
public final void setName(@Nullable String var1) {
this.name = var1;
}
@Nullable
public final Integer getAge() {
return this.age;
}
public final void setAge(@Nullable Integer var1) {
this.age = var1;
}
@JvmName(
name = "userDefinedGetName"
)
@Nullable
// getName() 으로 되어있던 함수명이 내가 지정해준 JvmName으로 변경되었다
public final String userDefinedGetName() {
return this.name;
}
}
클래스를 생성하고, 내부에 함수를 작성할때 함수명에 유의하여 작업해야함을 알았다.
참고자료
https://velog.io/@_im_ssu/JVM-signature-error-%EB%8C%80%EC%B2%98%ED%95%98%EA%B8%B0
JVM signature error 대처하기
부생성자에서 same JVM signature 오류가 발생한다면?
velog.io
https://codechacha.com/ko/kotlin-annotations/
Kotlin에서 자주 사용하는 annotation 정리
코틀린에서 자주 사용되는 @JvmName, @JvmStatic, @JvmField, @Throws, @JvmOverloads 등의 annotation들을 정리하였습니다. 코틀린은 JVM에서 동작하고 자바와 함께 사용되는 경우가 많기 때문에 이런 annotation들이
codechacha.com
'에러들' 카테고리의 다른 글
[Android] onBackPressedDispatcher : Unresolved references (0) | 2025.04.06 |
---|---|
TextSize "dp" 로 고정해 둔 값이 풀리는 경우 (1) | 2023.11.02 |