코틀린에서 제네릭(제네릭 매개변수)은 기본적으로 타입 소거(type erasure)됩니다. 실행 중에 타입 정보가 없습니다. 이는 리플렉션, 타입 변환 및 타입 주석 읽기를 복잡하게 만듭니다. 대부분의 작업에 대해서는 괜찮지만 일반 제네릭은 Java와 유사하게 작동합니다.
인라인 함수와 reified 매개변수는 컴파일러에게 호출 시 구체적인 타입을 "주입하도록" 강제할 수 있게 하며, 이를 통해 함수가 실행 시간에 타입과 함께 작업할 수 있게 됩니다(예: 검사, 리플렉션을 통해 새로운 인스턴스를 생성하는 등). 그러나 reified는 오직 inline 함수의 매개변수에만 적용될 수 있습니다.
비교 예제:
// 일반 제네릭 fun <T> printType(t: T) { println(t.javaClass) // List<Int> 등에서 ClassCastException을 발생시킵니다. } // reified 사용 inline fun <reified T> printType(t: T) { println(T::class.simpleName) } fun main() { printType(123) // 출력: Int printType("hello") // 출력: String }
응용 사례: 타입 검사, 캐스팅, 리플렉션, 인스턴스 생성 등에서 주로 사용되며, 다른 방법으로 타입을 얻을 수 없는 경우에 사용됩니다.
["구체화된 타입을 가진 함수가 비인라인일 수 있습니까?"]
reified는 인라인 함수에서만 작동합니다. 그렇지 않으면 컴파일 타임에 타입 주입이 불가능합니다.잘못된 사용 예:
fun <reified T> failFunction() {} // 컴파일 오류: reified 타입 매개변수는 인라인 함수에서만 사용될 수 있습니다.
올바른 예:
inline fun <reified T> goodFunction() {}
이야기
프로젝트에서 제네릭 매개변수를 가진 함수를 통해 JSON 문자열을 임의의 타입으로 일반적으로 파싱해야 했습니다. 표준 구현인
fun <T> parse(json: String): T는 타입 소거 때문에 올바르게 작동하지 않았습니다. 컬렉션 및 제네릭 모델에 대한 Class<T>를 가져올 수 없었습니다. 인라인과 구체화된 타입을 통해 문제는 사라졌습니다.
이야기
한 개발자는 인라인 및 구체화된 타입을 사용하지 않고 일반 생성자
T()를 통해 타입 T의 인스턴스를 생성하려고 했습니다. 컴파일 타임에 타입 정보가 소거되었기 때문에 오류가 발생했습니다.inline fun <reified T: Any>로 변경하여 언어의 표준 수단으로 모든 것을 해결할 수 있었습니다.
이야기
일반 함수(비인라인)에서 reified를 사용하려고 할 때 IDE가 혼란스러운 컴파일 오류를 발생시켰습니다. 개발자는 그 원인을 오랫동안 찾다가 문서를 공부하고 인라인을 추가함으로써 함수를 수정했습니다.