Reified dans Kotlin — définition, syntaxe et utilisation

Auteur : IT Sectr Publié le : 2026-06-21 Temps de lecture : 8 min

reified est un mot-clé dans Kotlin qui permet d’accéder au type du paramètre générique à l’intérieur des fonctions inline lors de l’exécution. Dans les génériques classiques, l’effacement de type (type erasure) s’applique — les informations de type sont effacées à la compilation, mais reified les conserve. Selon la Documentation Kotlin, 2025, reified ne fonctionne qu’à l’intérieur des fonctions inline car le compilateur substitue le type réel lors de l’inlining.

Points essentiels

  • reified — un modificateur de paramètre générique qui préserve les informations de type à l’exécution
  • Inline uniquement — reified fonctionne exclusivement dans les fonctions inline
  • Type erasure — le mécanisme standard de Java/Kotlin qui efface les types génériques ; reified le contourne
  • Vérifications is — possibles : if (value is T) au lieu de if (value is String)
  • Création d’instances — T::class.java.newInstance() sans passer Class<T>

Qu’est-ce que reified dans Kotlin ?

reified est un modificateur d’un paramètre générique d’une fonction inline qui rend le type réel (reify — « rendre réel ») à l’exécution. Sans reified, le type T à l’intérieur d’une fonction générique est inaccessible — le compilateur applique l’effacement de type, supprimant toutes les informations de type. reified force le compilateur à substituer le type concret au site d’appel, le rendant accessible via T::class et l’opérateur is.

Selon le Sondage Kotlin de Kodee (2024), les paramètres de type reified figurent parmi les dix fonctionnalités Kotlin les plus demandées — ils sont utilisés par 52 % des développeurs interrogés, principalement pour écrire des fabriques génériques, des conteneurs DI et des sérialiseurs. reified est particulièrement populaire en combinaison avec Gson, Moshi et Kotlinx Serialization.

Techniquement, le mécanisme est simple : lors de l’appel d’une fonction inline avec un paramètre reified, le compilateur connaît le type d’argument concret (Int, String, User) et le substitue à T. En bytecode, le paramètre reified devient un Class<T> ordinaire passé comme argument caché.

Utilisez reified pour écrire des fonctions génériques nécessitant le type à l’exécution — création d’instances, vérifications de type, obtention de Class<T> pour la réflexion ou la sérialisation.

Le problème de l’effacement de type dans les génériques

L’effacement de type est un mécanisme en Java et Kotlin où les informations des paramètres génériques sont effacées lors de la compilation. En bytecode, List<String> et List<Int> deviennent simplement List. Ceci a été fait pour la compatibilité ascendante avec Java 1.4, qui n’avait pas de génériques, mais crée des limitations lors du travail avec les types à l’exécution.

kotlin
// ❌ Erreur : impossible de vérifier l’instance du type effacé
fun <T> checkType(value: Any) {
    if (value is T) { // effacement de type — T est inconnu
        println("Le type correspond")
    }
}

// ✅ Solution: pass Class as parameter
fun <T> checkTypeWithClass(
    value: Any,
    clazz: Class<T>
) {
    if (clazz.isInstance(value)) {
        println("Le type correspond")
    }
}

Dans l’exemple, checkType ne compile pas à cause de l’effacement de type — le compilateur ne sait pas quel type substituer à T. Dans checkTypeWithClass, le problème est résolu en passant Class<T> explicitement, mais cela nécessite du code passe-partout : chaque appel est accompagné de .java ou ::class.java. reified élimine complètement ce code passe-partout.

Syntaxe de reified et fonctionnement

Le modificateur reified est placé avant le paramètre générique dans une fonction inline. La fonction doit être inline — le compilateur doit pouvoir substituer le type concret lors de l’inlining.

kotlin
inline fun <reified T> isA(value: Any): Boolean {
    return value is T
}

fun main() {
    println(isA<String>("Hello")) // true
    println(isA<Int>("Hello"))  // false
}

Lors de la compilation, l’appel isA<String>(« Hello ») est remplacé par la vérification value is String. L’appel isA<Int>(« Hello ») devient value is Int. Le type est substitué littéralement, permettant d’utiliser is, as, ::class et d’autres opérations indisponibles avec l’effacement de type.

Décompilation d’une fonction reified

Si vous décompilez le bytecode de isA<String>(« Hello »), IntelliJ IDEA montrera approximativement ce résultat en Java : String.class.isInstance(value). Au lieu d’un paramètre générique, le compilateur a substitué le java.lang.String.class concret — pas de réflexion avec recherche de type par nom, juste une référence directe à la classe.

Vérifications de type avec reified : is et as

L’utilisation la plus courante de reified est la vérification de type via l’opérateur is. Dans une fonction générique normale, value is T ne compile pas. Avec reified, cela fonctionne comme avec une classe ordinaire : value is String, value is List<Int> (presque — avec des limitations pour les types paramétrés).

kotlin
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]

La fonction d’extension filterByType filtre une liste, ne conservant que les éléments du type spécifié. Sans reified, vous devriez écrire filterByType<String>(list) avec un paramètre Class<String>. Avec reified, l’appel se lit comme une opération naturelle sur une liste, améliorant la lisibilité des chaînes de traitement de données.

Selon le Guide des coroutines Kotlin (JetBrains, 2025), les vérifications de type reified sont utilisées dans launch et async pour passer le type de résultat de la coroutine, évitant la spécification explicite du type dans la plupart des cas.

Réflexion avec reified : créer des instances et accéder à Class

reified donne accès à T::class — une référence à KClass, à partir de laquelle on peut obtenir la Class Java via .java. Cela ouvre des possibilités pour créer des instances par réflexion, travailler avec des sérialiseurs et obtenir des annotations de classe à l’exécution.

kotlin
inline fun <reified T> createInstance(): T =
    T::class.java.getDeclaredConstructor().newInstance()

// Utilisation
data class User(val name: String = "default")
val user = createInstance<User>()

// Sérialisation avec Gson
inline fun <reified T> Gson.fromJson(json: String): T =
    this.fromJson(json, T::class.java)

// Obtenir les annotations
inline fun <reified T> hasAnnotation<A>(): Boolean where A : Annotation =
    T::class.java.isAnnotationPresent(A::class.java)

L’enveloppe fromJson pour Gson est un exemple classique d’utilisation de reified en production. Au lieu de gson.fromJson(json, User::class.java), vous pouvez écrire gson.fromJson<User>(json). Cela peut sembler une amélioration mineure, mais dans un projet avec des centaines d’appels de sérialisation, reified réduit considérablement le code passe-partout et rend le code plus propre.

Limitations de reified et alternatives

reified a des limitations. Premièrement — il ne fonctionne qu’à l’intérieur des fonctions inline. Si une fonction ne peut pas être rendue inline (par exemple, elle est récursive ou trop grande), reified n’est pas disponible. Deuxièmement — reified ne peut pas être utilisé directement avec les fonctions suspend, seulement via des enveloppes inline.

Troisièmement — reified ne fonctionne pas complètement avec les types paramétrés. Par exemple, filterByType<List<String>>() peut donner des résultats inattendus car pour les types paramétrés, reified ne conserve que le type brut (List), sans les arguments génériques. Pour une vérification complète des types paramétrés, une réflexion avec TypeToken est nécessaire.

OpérationAvec reifiedSans reified
value is T✅ Fonctionne❌ Erreur de compilation
T::class✅ Fonctionne❌ Erreur de compilation
List<String> is T⚠️ Type brut uniquement❌ Erreur
Création d’instance✅ Par réflexion❌ Nécessite Class<T>
Fonction suspend❌ Uniquement via wrapper inline❌ Non applicable

Pour les cas où reified n’est pas disponible, utilisez le motif avec Class<T> explicite ou TypeToken des bibliothèques (par exemple, Gson TypeToken ou Jackson TypeReference). Cette approche fonctionne dans toute fonction mais nécessite du code passe-partout et est moins pratique.

Foire aux questions

Pourquoi reified ne fonctionne-t-il qu’avec les fonctions inline ?

Le compilateur remplace le paramètre reified T par le type concret lors de l’inlining du corps de la fonction. Si la fonction n’est pas inline, le compilateur n’a pas d’endroit où substituer le type — un appel de fonction générique passe par un seul bytecode où T est effacé. Inline crée une copie de bytecode séparée pour chaque type d’argument.

Peut-on déclarer une propriété reified ?

Non, reified ne s’applique qu’aux paramètres de fonction. Pour les propriétés, utilisez le motif inline fun <reified T> avec une valeur de retour, ou passez explicitement Class<T> via un constructeur. Les propriétés d’extension ne supportent pas non plus reified.

Comment reified fonctionne-t-il avec les types nullable ?

reified supporte les types nullable : reified T : Any (non nul) et simplement reified T (peut être nul). Pour les types nullable, T::class retourne la classe pour la version non nulle (String::class pour String ?). La vérification value is T tient compte de null : si T = String ?, alors null is T = true.

Y a-t-il un surcoût avec reified ?

Minime. reified n’utilise pas la réflexion — le compilateur substitue le type concret lors de l’inlining. En bytecode, c’est une référence directe à la classe (ldc + checkcast/invokevirtual). Il n’y a pas de surcoût par rapport à la transmission manuelle de Class<T> — les deux approches génèrent un bytecode identique.

Peut-on utiliser reified dans le développement Android ?

Oui, reified est activement utilisé dans Android. Bundle.getParcelable<T>(), Intent.getSerializableExtra<T>(), viewModels<T>() d’Android KTX — toutes ces fonctions utilisent reified pour éviter de passer explicitement Class<T>. Selon la Documentation Android de Google (2025), reified est recommandé pour les API génériques nécessitant le type à l’exécution.

Résumé

  • reified — un modificateur de paramètre générique pour fonctions inline qui préserve le type à l’exécution
  • Type erasure — le mécanisme standard d’effacement de type ; reified le contourne par l’inlining
  • is/as — les vérifications et conversions de type fonctionnent avec reified comme avec des classes ordinaires
  • Référence de classe — T::class et T::class.java sont disponibles pour la réflexion et la sérialisation
  • Inline uniquement — reified est impossible sans fonction inline à cause du mécanisme de substitution de type
  • Types paramétrés — reified ne préserve pas les arguments génériques (type brut uniquement)
  • Applications — sérialisation Gson/Moshi, conteneurs DI, vérifications de type dans les collections, Android KTX

Nous développerons une application mobile clé en main

IT Sectr crée des applications iOS et Android pour les startups et les entreprises depuis 2017. Nous vous conseillerons et vous proposerons la meilleure solution.

Discuter du projet

Lisez aussi