티스토리 뷰

코틀린

Reflection

pjm1n 2025. 10. 3. 22:23

Reflection

리플렉션은 프로그램의 구조를 런타임에 살펴볼 수 있는 언어 및 라이브러리 기능들의 집합이다.

Kotlin에서 함수와 속성은 일급 객체이며, 이들을 런타임에 조사할 수 있는 능력은 함수형 또는 리액티브 스타일 프로그래밍을 할 때 중요하다.

JVM 의존성

JVM 플랫폼에서, Kotlin 컴파일러에는 리플렉션 기능을 사용하기 위해 필요한 런타임 컴포넌트가 별도의 아티팩트(kotlin-reflect.jar)로 포함되어 있다. 이는 리플렉션 기능을 사용하지 않는 애플리케이션의 런타임 라이브러리 크기를 줄이기 위해서다.

Gradle이나 Maven 프로젝트에서 리플렉션 사용하기

dependencies {
    implementation(kotlin("reflect"))
}

기타

  • Gradle이나 Maven을 사용하지 않는 경우, 프로젝트 classPath에 Kotlin-reflect.jar가 포함되어 있어야한다.
  • 커멘드 라인 컴파일러나 Ant를 사용하는 인텔리제이 같은 IDEA 프로젝트 등에서는 기본적으로 포함되어있다.
  • 커멘드 라인 컴파일러나 Ant에서는 -no -reflect 컴파일 옵션을 사용하면 kotlin-reflect.jar를 classPath에서 제외할 수 있다.

클래스 참조

가장 기본적인 리플렉션 기능은 Kotlin 클래스의 런타임 참조를 얻는 것이다. 정적으로 알려진 Kotlin 클래스의 참조를 얻으려면, 클래스 리터럴 문법(class literal syntax)을 사용할 수 있다.

val c = MyClass::class

이때 얻는 참조는 KClass타입이다.

JVM에서 주의할 점

Kotlin 클래스 참조(Kclass)는 Java 클래스 참조(Class)와 동일하지 않다. Java클래스 참조(Class)와 동일하지 않다. Java 클래스 참조가 필요하면, KClass 인스턴스의 .java 프로퍼티를 사용하면 된다.

val javaClass = MyClass::class.java

바운드 클래스 참조

특정 객체의 클래스 참조도 동일하게 ::class 문법을 사용하여 얻을 수 있다. 객체를 리시버로 사용하면 된다.

val widget: Widget = ...
assert(widget is GoodWidget) { "Bad widget: ${widget::class.qualifiedName}" }

함수 참조

다음과 같은 함수가 있다고 가정하자

fun isOdd(x: Int) = x % 2 != 0

이를 isOdd(5)로 호출할 수 있지만, 다음과 같이 함수를 함수 타입 값으로 사용하여 다른 함수에 전달할 수 있다.

val numbers = listOf(1, 2, 3)
println(numbers.filter(::isOdd))

여기서 ::isOdd(Int) -> Boolean 타입의 값이다.

프로퍼티 참조

프로퍼티를 일급 객체로 다루려면 ::연산자를 사용한다.

val x = 1

fun main() {
    println(::x.get())
    println(::x.name)
}

여기서 ::x 표현식은 KProperty0<Int> 타입의 프로퍼티 객체로 평가된다. get()으로 값을 읽거나 name 속성을 통해 프로퍼티 이름을 가져올 수 있다.

Java 리플렉션과의 상호운용성

JVM에서는, 코틀린 표준 라이브러리가 Java 리플렉션 객체 ↔ Kotlin 객체 간 매핑을 지원하는 확장함수를 제공한다.

예제를 들면 다음과 같다.

import kotlin.reflect.jvm.*

class A(val p: Int)

fun main() {
    println(A::p.javaGetter) // 출력: "public final int A.getP()"
    println(A::p.javaField)  // 출력: "private final int A.p"
}

A::p.javaGetter는 해당 프로퍼티의 Java getter 메서드를 반환한다.

A::p.javaField는 해당 프로퍼티의 실제 baking field를 반환한다.

Java 클래스 ↔ Kotlin 클래스

Java 클래스에서 대응되는 Kotlin 클래스(Kclass)를 얻고 싶다면 .kotlin확장프로퍼티를 사용한다.

fun getKClass(o: Any): KClass<Any> = o.javaClass.kotlin

o.javaClass는 Java Class<?>객체이며 o.javaClass.Kotlin은 KClass객체이다.

생성자 참조

생성자도 함수나 프로퍼티처럼 참조 가능하다. 즉, 특정 함수 타입을 기대하는 곳에, 생성자를 그대로 전달해서 사용할 수 있다. 생성자 참조는 :: 연산자 뒤에 클래스 이름을 붙여 사용한다.

예제 코드는 다음과 같다.

class Foo

fun function(factory: () -> Foo) {
    val x: Foo = factory()
}

여기서 function은 Foo 타입 객체를 반환하는 함수를 인자로 받고 있다. 따라서 Foo 클래스의 인자가 없는 기본 생성자를 참조해서 넘겨줄 수 있다.

'코틀린' 카테고리의 다른 글

StateFlow, SharedFlow  (0) 2025.11.18
디미터의 법칙  (0) 2025.03.30
코틀린 문법(Sealed Interface)  (0) 2025.03.30
코틀린 문법(배열)  (0) 2024.08.19
Kotlin에서 property, JAVA에서의 field와 property  (0) 2024.08.05
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2026/01   »
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
글 보관함