ProgrammationDéveloppeur Kotlin / Ingénieur Performance

Comment fonctionnent les accesseurs de propriété en ligne (getters et setters en ligne) en Kotlin ? Quelles sont les spécificités et les subtilités de leur utilisation, comment affectent-ils les performances et où peuvent survenir des erreurs inattendues ? Donnez un exemple.

Réussissez les entretiens avec l'assistant IA Hintsage

Réponse

Kotlin permet de marquer les getters et setters des propriétés avec le modificateur inline. Cela donne au compilateur le droit d'inliner (intégrer) le code de l'accesseur directement aux lieux d'appel pour optimiser les performances.

Exemple :

val foo: Int inline get() = expensiveCalculation()
  • En raison de l'inlining, la fonction getter n'entraîne pas de frais généraux d'appel (par exemple, dans des boucles), si le code de l'accesseur est court.
  • L'inlining est possible uniquement pour les getters sans état (stateless) ; toute la logique ne peut pas être inlinée.
  • Vous ne pouvez pas utiliser inline pour le getter/setter s'il contient des paramètres génériques reified ou des expressions lambda avec cross-linking.

Meilleures pratiques : utiliser l'accesseur inline uniquement pour des expressions très courtes, fréquemment appelées sans effets secondaires.


Question piège

Si une annotation avec réflexion est ajoutée à une propriété avec un getter/setter en ligne (par exemple, utilisée via KProperty), l'inlining fonctionnera-t-il ?

Réponse : Non. Si la propriété est utilisée via l'API de réflexion ou fait référence à KProperty, le compilateur ne pourra pas intégrer le getter/setter, et ils resteront des méthodes normales. L'inlining se produit uniquement lors d'un accès direct dans le code.


Histoire

Perte de performance due au travail de réflexion avec le getter inline :

Nous avons réécrit une propriété chaude avec un getter inline, espérant éliminer les appels superflus. Plus tard, nous avons ajouté une validation via KProperty – au final, les appels ont commencé à se faire via réflexion, annulant complètement l'avantage de l'accesseur inline.


Histoire

Effets secondaires indésirables lors de l'inlining :

Le getter inline faisait de la journalisation :

inline get() { println("accessed!") return field }

Cette implémentation entraînait une journalisation inattendue à de nombreux endroits, lorsque la propriété était fréquemment lue dans différentes parties du code, ce qui encombrait considérablement les journaux.


Histoire

Violation de l'ABI en raison de la modification d'une propriété inline :

Nous avons changé la logique du getter inline dans la bibliothèque, sans recompilation des modules dépendants, les clients ont continué à utiliser l'ancienne signature – l'ABI étendu plus l'inlining a conduit à une incompatibilité et à une défaillance cachée des clients lors de la mise à jour.