-
Kotlin - Reflection 과 생성자Kotiln 2021. 8. 4. 15:56
Reflection 을 이용하여 인스턴스를 생성하는 방법을 알아봅시다.
간단한 Person data class 를 생성했습니다.
data class Person( var name: String, var age: Number = 20 )
age 프로퍼티에 기본 값으로 20 을 주었습니다.
println("생성자 조회") println(Person::class.constructors)
생성자 조회 [fun <init>(kotlin.String, kotlin.Number): chung.study.Person]
먼저 생성자를 조회해보겠습니다.
Person 클래스를 생성한 것 과 같이 파라미터가 2개인 생성자가 조회됐습니다.
생성자는
KFunction
인터페이스이며KCallable
인터페이스를 상속받고 있습니다.KCallable
인터페이스 안에는call
,callBy
메소드가 있습니다.두 메소드를 이용하여 Person 객체를 생성해보겠습니다.
call
을 이용한 객체 생성println("생성자 조회") println(Person::class.constructors) println("call 을 이용한 생성") Person::class.primaryConstructor?.call("홍길동", 30)?.let { println(it) }
call
메소드에 매개변수를 넣고 결과를 출력해보겠습니다.call 을 이용한 생성 Person(name=홍길동, age=30)
예상한 결과대로 name=홍길동, age=30 인 객체가 생성되었습니다.
Person 클래스를 생성할 때 age 에 기본 값을 지정했기 때문에 age 에 들어갈 매개변수를 지우고 생성해보겠습니다.
println("call 을 이용한 생성 (기본값)") Person::class.primaryConstructor?.call("홍길동")?.let { println(it) }
java.lang.IllegalArgumentException: Callable expects 2 arguments, but 1 were provided. at kotlin.reflect.jvm.internal.calls.Caller$DefaultImpls.checkArguments(Caller.kt:20) at kotlin.reflect.jvm.internal.calls.CallerImpl.checkArguments(CallerImpl.kt:15) at kotlin.reflect.jvm.internal.calls.CallerImpl$Constructor.call(CallerImpl.kt:40) at kotlin.reflect.jvm.internal.KCallableImpl.call(KCallableImpl.kt:108)
생성하지 못하고 2개의 매개변수를 예상했지만 한개만 제공되었다는 에러를 볼 수 있습니다.
기본 값을 이용하려면
callBy
메소드를 사용해야 합니다.callBy
메소드는 매개변수로Map<KParameter, Any?>
를 받습니다.val nameKParameter = Person::class.primaryConstructor?.findParameterByName("name") val ageKParameter = Person::class.primaryConstructor?.findParameterByName("age") if (nameKParameter != null && ageKParameter != null) { println("callBy 를 이용한 생성") Person::class.primaryConstructor?.callBy(mapOf(nameKParameter to "홍길동", ageKParameter to 30))?.let { println(it) } println("callBy 를 이용한 생성 (순서 상관 없다)") Person::class.primaryConstructor?.callBy(mapOf(ageKParameter to 30, nameKParameter to "홍길동"))?.let { println(it) } println("callBy 를 이용한 생성 (기본값)") Person::class.primaryConstructor?.callBy(mapOf(nameKParameter to "홍길동"))?.let { println(it) } }
생성자에서
findParameterByName
메소드를 사용하여 name 과 age 에 해당하는 KParameter 를 가져 온 뒤 각각 값을 넣고callBy
메소드의 매개변수로 넣어주었습니다.callBy 를 이용한 생성 Person(name=홍길동, age=30) callBy 를 이용한 생성 (순서 상관 없다) Person(name=홍길동, age=30) callBy 를 이용한 생성 (기본값) Person(name=홍길동, age=20)
기본 값이 들어간 객체가 생성되었습니다.
callBy
메소드는 매개변수와 파라미터( 코드에서 매개변수로 전달한 Map) 를 매핑하여 결과를 반환하는 데 만약 파라미터에 매핑된 값이 없으면 기본 값을 사용합니다.Person::class.primaryConstructor?.callBy(mapOf(ageKParameter to 30))?.let { println(it) }
기본 값이 없는 파라미터를 넣어주지 않으면 다음과 같이 에러가 발생합니다.
java.lang.IllegalArgumentException: No argument provided for a required parameter: parameter #0 name of fun <init>(kotlin.String, kotlin.Number): chung.study.Person
blog-source/kotlin-constructor-reflection at master · sinna94/blog-source
반응형'Kotiln' 카테고리의 다른 글
Kotlin - jackson 을 이용하여 객체를 json 으로 변환할 때 주의점 (4) 2021.03.24 코틀린과 삼항 연산자 (1) 2021.03.19 kotlin gradle 프로젝트에 ktlint 적용하기 (0) 2020.11.07 [Kotlin] 고차 함수 (0) 2020.06.30 [Kotlin] 엔티티로 테이블 이름 가져오기 (0) 2020.04.13