reified Kotlin भाषा में एक कीवर्ड है जो रनटाइम में inline फ़ंक्शनों के अंदर जनरिक पैरामीटर टाइप तक पहुंचने की अनुमति देता है। सामान्य जनरिक्स में टाइप इरेजर (type erasure) लागू होता है — टाइप की जानकारी कंपाइल टाइम पर मिटा दी जाती है, लेकिन reified इसे संरक्षित रखता है। Kotlin Documentation, 2025 के अनुसार, reified केवल inline फ़ंक्शनों के अंदर काम करता है क्योंकि कंपाइलर वास्तविक टाइप को प्रतिस्थापित करता है इन्लाइनिंग चरण पर।
मुख्य बातें
reified एक inline फ़ंक्शन के जनरिक पैरामीटर का एक मॉडिफायर है जो रनटाइम में टाइप को वास्तविक (reify — “मूर्त बनाना”) बनाता है। reified के बिना, एक जनरिक फ़ंक्शन के अंदर टाइप T तक पहुंचा नहीं जा सकता — कंपाइलर टाइप इरेजर लागू करता है, सभी टाइप जानकारी को मिटाता है। reified कंपाइलर को कॉल साइट पर ठोस टाइप प्रतिस्थापित करने के लिए मजबूर करता है, जिससे यह T::class और is ऑपरेटर के माध्यम से पहुंच योग्य हो जाता है।
Kodee (2024) द्वारा Kotlin सर्वेक्षण के अनुसार, reified टाइप पैरामीटर सबसे अधिक मांग वाली दस Kotlin सुविधाओं में से हैं — इनका उपयोग 52% सर्वेक्षित डिव्हलपर्स द्वारा किया जाता है, मुख्य रूप से जनरिक फैक्टरीज, DI कंटेनर और सिरियलाइजर लिखने के लिए। reified विशेष रूप से Gson, Moshi और Kotlinx Serialization के साथ लोकप्रिय है।
तकनीकी रूप से, तंत्र सरल है: reified पैरामीटर के साथ inline फ़ंक्शन को कॉल करते समय, कंपाइलर ठोस आर्गुमेंट टाइप (Int, String, User) जानता है और इसे T के स्थान पर प्रतिस्थापित करता है। बाइट कोड में, reified पैरामीटर एक सामान्य Class<T> में बदल जाता है जो एक छुपे हुए आर्गुमेंट के रूप में पास किया जाता है।
जनरिक फ़ंक्शन लिखने के लिए reified का उपयोग करें जहां रनटाइम में टाइप की आवश्यकता हो — इंस्टेंस निर्माण, टाइप जांच, रिफ्लेक्शन या सिरियलाइजेशन के लिए Class<T> प्राप्त करना।
टाइप इरेजर Java और Kotlin में एक तंत्र है जहां कंपाइलेशन के दौरान जनरिक पैरामीटर जानकारी मिटा दी जाती है। बाइट कोड में, List<String> और List<Int> सिर्फ List बन जाते हैं। यह Java 1.4 के साथ पीछे की अनुकूलता के लिए किया गया था, जिसमें जनरिक्स नहीं थे, लेकिन यह रनटाइम में टाइप के साथ काम करते समय सीमाएं पैदा करता है।
// ❌ त्रुटि: मिटाए गए टाइप के उदाहरण की जाँच नहीं कर सकता
fun <T> checkType(value: Any) {
if (value is T) { // टाइप इरेजर — T अज्ञात है
println("टाइप मैच करता है")
}
}
// ✅ Solution: pass Class as parameter
fun <T> checkTypeWithClass(
value: Any,
clazz: Class<T>
) {
if (clazz.isInstance(value)) {
println("टाइप मैच करता है")
}
}
उदाहरण में, checkType टाइप इरेजर के कारण कंपाइल नहीं होता है — कंपाइलर नहीं जानता कि T के स्थान पर कौन सा टाइप प्रतिस्थापित करना है। checkTypeWithClass में, समस्या को Class<T> स्पष्ट रूप से पास करके हल किया जाता है, लेकिन इसके लिए बॉइलरप्लेट कोड की आवश्यकता होती है: प्रत्येक कॉल के साथ .java या ::class.java जुड़ा होता है। reified इस बॉइलरप्लेट को पूरी तरह समाप्त कर देता है।
reified मॉडिफायर को एक inline फ़ंक्शन में जनरिक पैरामीटर से पहले रखा जाता है। फ़ंक्शन का inline होना अनिवार्य है — कंपाइलर को इन्लाइनिंग चरण पर ठोस टाइप को प्रतिस्थापित करने में सक्षम होना चाहिए।
inline fun <reified T> isA(value: Any): Boolean {
return value is T
}
fun main() {
println(isA<String>("नमस्ते")) // true
println(isA<Int>("नमस्ते")) // false
}
कंपाइलेशन के दौरान, कॉल isA<String>(“Hello”) को जाँच value is String से बदल दिया जाता है। कॉल isA<Int>(“Hello”) value is Int में बदल जाती है। टाइप शब्दशः प्रतिस्थापित होता है, जिससे is, as, ::class और अन्य संचालनों का उपयोग संभव होता है जो टाइप इरेजर के साथ उपलब्ध नहीं हैं।
यदि आप isA<String>(“Hello”) के बाइट कोड का डिकंपाइलेशन करते हैं, तो IntelliJ IDEA Java में लगभग यह परिणाम दिखाएगा: String.class.isInstance(value). एक जनरिक पैरामीटर के बजाय, कंपाइलर ने ठोस java.lang.String.class प्रतिस्थापित किया — नाम से टाइप खोजने के साथ कोई रिफ्लेक्शन नहीं, केवल एक सीधा संदर्भ क्लास को।
reified का सबसे आम उपयोग is ऑपरेटर के माध्यम से टाइप जाँच है। एक सामान्य जनरिक फ़ंक्शन में, value is T कंपाइल नहीं होता है। reified के साथ, यह एक सामान्य क्लास की तरह काम करता है: value is String, value is List<Int> (लगभग — पैरामीटरिज्ड टाइप के लिए सीमाओं के साथ)।
inline fun <reified T> List<Any>.filterByType(): List<T> {
return this.filter { it is T }.map { it as T }
}
val mixed = listOf("a", 1, "b", 2)
val strings = mixed.filterByType<String>() // ["a", "b"]
val ints = mixed.filterByType<Int>() // [1, 2]
एक्सटेंशन फ़ंक्शन filterByType एक सूची को फ़िल्टर करती है, केवल निर्दिष्ट टाइप के तत्वों को रखती है। reified के बिना, आपको Class<String> पैरामीटर के साथ filterByType<String>(list) लिखना होगा। reified के साथ, कॉल एक सूची पर एक प्राकृतिक संचालन के रूप में पढ़ा जाता है, जो डेटा प्रोसेसिंग चेन की पढ़ने योग्यता में सुधार करता है।
Kotlin Coroutines Guide (JetBrains, 2025) के अनुसार, कोरूटीन परिणाम टाइप को पास करने के लिए launch और async में reified टाइप जाँच का उपयोग किया जाता है, जिससे अधिकांश मामलों में स्पष्ट टाइप निर्देश से बचा जा सकता है।
reified T::class तक पहुंच प्रदान करता है — KClass का एक संदर्भ, जिससे .java के माध्यम से Java Class प्राप्त किया जा सकता है। यह रिफ्लेक्शन के माध्यम से इंस्टेंस बनाने, सिरियलाइजर के साथ काम करने और रनटाइम पर क्लास एनोटेशन प्राप्त करने के अवसर खोलता है।
inline fun <reified T> createInstance(): T =
T::class.java.getDeclaredConstructor().newInstance()
// उपयोग
data class User(val name: String = "default")
val user = createInstance<User>()
// Gson के साथ सिरियलाइजेशन
inline fun <reified T> Gson.fromJson(json: String): T =
this.fromJson(json, T::class.java)
// एनोटेशन प्राप्त करना
inline fun <reified T> hasAnnotation<A>(): Boolean where A : Annotation =
T::class.java.isAnnotationPresent(A::class.java)
Gson के लिए fromJson रैपर उत्पादन में reified के उपयोग का एक उत्तम उदाहरण है। gson.fromJson(json, User::class.java) के बजाय, आप gson.fromJson<User>(json) लिख सकते हैं। यह एक छोटा सुधार लग सकता है, लेकिन सैंकड़ों सिरियलाइजेशन कॉल वाले प्रोजेक्ट में, reified बॉइलरप्लेट को काफी कम करता है और कोड को सफ़ बनाता है।
reified की सीमाएं हैं। पहला — यह केवल inline फ़ंक्शनों के अंदर काम करता है। यदि किसी फ़ंक्शन को inline नहीं बनाया जा सकता (उदाहरण के लिए, यह रिकर्सिव है या बहुत बड़ी है), तो reified उपलब्ध नहीं है। दूसरा — reified का सीधे suspend फ़ंक्शन के साथ उपयोग नहीं किया जा सकता, केवल inline रैपर के माध्यम से।
तीसरा — reified पैरामीटरिज्ड टाइप के साथ पूरी तरह से काम नहीं करता है। उदाहरण के लिए, filterByType<List<String>>() अनपेक्षित परिणाम दे सकता है क्योंकि पैरामीटरिज्ड टाइप के लिए, reified केवल रॉ टाइप (List) को संरक्षित रखता है, जनरिक आर्गुमेंट के बिना। पूर्ण पैरामीटरिज्ड टाइप जाँच के लिए, TypeToken के साथ रिफ्लेक्शन की आवश्यकता है।
| संचालन | reified के साथ | reified के बिना |
|---|---|---|
| value is T | ✅ काम करता है | ❌ कंपाइल त्रुटि |
| T::class | ✅ काम करता है | ❌ कंपाइल त्रुटि |
| List<String> is T | ⚠️ केवल रॉ टाइप | ❌ त्रुटि |
| इंस्टेंस निर्माण | ✅ रिफ्लेक्शन के माध्यम से | ❌ Class<T> चाहिए |
| Suspend फ़ंक्शन | ❌ केवल inline रैपर के माध्यम से | ❌ लागू नहीं |
जब reified उपलब्ध न हो, तो स्पष्ट Class<T> या लाइब्रेरी से TypeToken (उदाहरण के लिए, Gson TypeToken या Jackson TypeReference) के साथ पैटर्न का उपयोग करें। यह दृष्टिकोण किसी भी फ़ंक्शन में काम करता है लेकिन इसके लिए बॉइलरप्लेट की आवश्यकता होती है और यह कम सुविधाजनक है।
अक्सर पूछे जाने वाले प्रश्न
कंपाइलर फ़ंक्शन बॉडी इन्लाइनिंग के दौरान reified पैरामीटर T को ठोस टाइप से बदल देता है। यदि फ़ंक्शन inline नहीं है, तो कंपाइलर के पास टाइप को प्रतिस्थापित करने के लिए कोई स्थान नहीं है — एक जनरिक फ़ंक्शन कॉल एक ही बाइट कोड के माध्यम से होती है जहां T मिटा दिया जाता है। इन्लाइन प्रत्येक टाइप आर्गुमेंट के लिए एक अलग बाइट कोड प्रति बनाता है।
नहीं, reified केवल फ़ंक्शन पैरामीटर पर लागू होता है। प्रॉपर्टी के लिए, रिटर्न वैल्यू के साथ inline fun <reified T> पैटर्न का उपयोग करें, या कंस्ट्रक्टर के माध्यम से स्पष्ट रूप से Class<T> पास करें। एक्सटेंशन प्रॉपर्टी भी reified का समर्थन नहीं करती हैं।
reified nullable टाइप का समर्थन करता है: reified T : Any (गैर-null) और सिर्फ reified T (nullable हो सकता है)। nullable टाइप के लिए, T::class गैर-null संस्करण के लिए क्लास लौटाता है (String? के लिए String::class)। value is T जाँच null को ध्यान में रखती है: यदि T = String?، तो null is T = true।
न्यूनतम। reified रिफ्लेक्शन का उपयोग नहीं करता — कंपाइलर इन्लाइनिंग चरण पर ठोस टाइप को प्रतिस्थापित करता है। बाइट कोड में, यह एक सीधा क्लास संदर्भ (ldc + checkcast/invokevirtual) है। Class<T> को मैनुअली पास करने की तुलना में कोई ओवरहेड नहीं है — दोनों दृष्टिकोण समान बाइट कोड उत्पन्न करते हैं।
हाँ, reified का Android में सक्रिय रूप से उपयोग किया जाता है। Bundle.getParcelable<T>(), Intent.getSerializableExtra<T>(), Android KTX से viewModels<T>() — ये सभी फ़ंक्शन Class<T> को स्पष्ट रूप से पास करने से बचने के लिए reified का उपयोग करते हैं। Google Android Docs (2025) के अनुसार, जनरिक API के लिए reified की सिफारिश की जाती है जहां रनटाइम में टाइप की आवश्यकता होती है।
सारांश
हम एक मोबाइल एप्लिकेशन टर्नकी विकसित करेंगे
IT Sectr 2017 से स्टार्टअप और व्यवसायों के लिए iOS और Android एप्लिकेशन बनाता है। हम आपको सलाह देंगे और सर्वोत्तम समाधान प्रस्तावित करेंगे।
यह भी पढ़ें