본문 바로가기

개발/이게 왜 안돼?

[코틀린] varargs 를 넘기고 싶은데 잘 안돼!

이슈

messageConverter를 이용해서 인자들을 넘겨서 메세지를 출력해주고 싶다. 

출력하고 싶은 템플릿은 다음과 같았다. 다음과 같이 3개의 인자를 받는다.

안녕하세요. 예시 {0} 은 {1} 이고 {2} 입니다.

인자 3개를 varargs로 해서 잘 넘겨주고 있다고 생각했는데 출력값이 다음과 같이 나오고 있었다.

안녕하세요. 예시 java.lang.String;@279999ac 은 {1} 이고 {2} 입니다.

 

흠... 아무리 봐도 쟤는 배열의 주소값이 넘어가고 있는데...

varargs에 대한 이해가 부족해서 2시간 넘게 헤맸다.

 

기존코드

다음과 같이 getMessage를 호출하고 있었다.

Foo.A.printMessage(arrayOf("one", 2, "쓰리"))

enum class Foo(code: String) {

   A ("template.a"),
   B ("template.b"),
   ;

   fun printMessage(vararg args: Any) = MessageSource.getMessage(code, args)
}

 

수정코드

Foo.A.printMessage(arrayOf("one", 2, "쓰리"))

enum class Foo(code: String) {

   A ("template.a"),
   B ("template.b"),
   ;

   fun printMessage(args: Array<Any>) = MessageSource.getMessage(code, *args)
}

 

 

원인

기존코드에서 array를 넘겨주었는데 varargs는 어레이 타입의 인자 1개만 받는다고 인식한다.

그렇기에 printMessage가 받은 인자는 1개이고 이를 getMessage에 넘겨주게 되면 어레이 타입의 인자 1개만 넘겨준 셈이 되어서 자꾸 이상한 값이 출력됐던 것.

 

printMessage에서 어레이 타입으로 받고 spread operator (*) 를 이용하여 넘겨주면 해결 완료!

 

varargs

vararg에 값을 넘길때 각각의 인자를 하나씩 넘길 수 있지만 본문과 같이 array의 각 원소를 인자로 넘기고 싶다면 spread operator (*) 를 사용하여 넘겨주면 된다.

fun asList(vararg ts: T) {}

val a = arrayOf(1, 2, 3)
val list = asList(-1, 0, *a, 4)
 

만약 primitive type array를 인자로 넘기고 싶다면 .toTypedArray() 로 변환 해줘야 한다.

val a = intArrayOf(1, 2, 3) // IntArray is a primitive type array
val list = asList(-1, 0, *a.toTypedArray(), 4)

 

 

참고

https://kotlinlang.org/docs/functions.html#variable-number-of-arguments-varargs