Reflection ve vývoji aplikací — co to je, mechanismy reflexe a jak je používat

Autor: IT Sectr Publikováno: 2026-05-17 Doba čtení: 8 min

Reflection (reflexe) — mechanismus běhového prostředí, který umožňuje kódu zkoumat vlastní strukturu: získávat třídy, metody, pole a anotace bez znalosti typů ve fázi kompilace. Tento nástroj stojí v základu mnoha mobilních frameworků — serializace JSON (Gson, Moshi), dependency injection (Dagger, Koin) a testovacích runnerů (JUnit, XCTest). Podle Oracle Java Reflection Tutorial, 2024 je reflection povinným prvkem platformy Java, který používají všechny velké knihovny.

Hlavní body

  • Reflection — přístup k metadatům tříd, metod a polí během provádění programu.
  • Java Reflection API poskytuje třídy Class, Method, Field a Constructor pro dynamickou analýzu.
  • Reflection v Kotlin používá KClass a KFunction, integrované s korutinami a serializací.
  • Objective-C Runtime — forma reflection přes class_copyMethodList a objc_getClass.
  • Výkon reflection je 10–100krát nižší než u přímých volání kvůli chybějícím optimalizacím JIT.

Co je to Reflection?

Reflection — schopnost programu pozorovat a měnit vlastní strukturu a chování za běhu. V objektově orientovaných jazycích to znamená získávání objektů Class, Method, Field a Constructor, které představují prvky programu jako data dostupná pro čtení a volání.

Termín „reflection” byl zaveden v komunitě umělé inteligence v roce 1982 (Brian Cantwell Smith) a implementován v jazyce Smalltalk. V mobilním vývoji se reflection poprvé objevil v Java ME a Objective-C (1986, NextStep). Dnes má každá velká mobilní platforma své vlastní reflection API: Java/Kotlin pro Android, Objective-C Runtime pro iOS, Swift Mirror API pro Swift.

Mechanismus reflection je založen na metadatech, která kompilátor ukládá do bajtkódu nebo binárního souboru. Android ukládá úplné informace o třídách do souborů DEX, iOS — do segmentu __objc_classlist v Mach-O. Runtime tato metadata načte do paměti a poskytuje API pro jejich procházení.

Jak funguje Reflection v Javě a Kotlinu

Java Reflection API je postaveno kolem třídy java.lang.Class. Jakýkoli objekt v Javě lze převést na Class přes .getClass() nebo Class.forName(). Z Class se získávají všechny metody, pole, konstruktory, anotace a nadtřídy. Kotlin dědí Java reflection a přidává vlastní KClass, KFunction, KProperty z balíčku kotlin.reflect.

kotlin
import kotlin.reflect.full.declaredMemberFunctions

data class User(
    val name: String,
    val email: String
)

fun inspectClass() {
    val kClass = User::class
    val properties = kClass.declaredMemberProperties
    val functions = kClass.declaredMemberFunctions

    properties.forEach { prop ->
        println("Vlastnost: ${prop.name}, typ: ${prop.returnType}")
    }
}

V tomto příkladu KClass poskytuje metadata data class User. declaredMemberProperties vrací seznam vlastností s jejich typy a gettery. Reflection v Kotlinu je úzce integrován s korutinami: KFunction podporuje modifikátor suspend, což umožňuje volat asynchronní metody přes reflection.

Java Reflection: Class, Method, Field

Java reflection pracuje s Class<?>, Method.setAccessible() a Field.get(). setAccessible(true) vypíná kontrolu přístupu Java language access control pro private prvky. Je to mocný, ale nebezpečný mechanismus: na Androidu od API 28 může volání setAccessible na skrytých systémových metodách způsobit InaccessibleObjectException.

java
// Java reflection: volání soukromé metody
Class clazz = Class.forName("com.example.MyClass");
Object instance = clazz.getDeclaredConstructor().newInstance();
Method method = clazz.getDeclaredMethod("privateMethod", String.class);
method.setAccessible(true);
method.invoke(instance, "reflection test");

Kód demonstruje Class.forName() — dynamické načítání třídy podle řetězcového názvu. To je základ pluginových architektur: třída může být ve fázi kompilace neznámá, ale v runtime načtena a spuštěna přes reflection. getDeclaredMethod(„privateMethod”, ...) najde metodu podle názvu a typů parametrů a invoke ji spustí.

Objective-C Runtime: alternativní model reflexe

Objective-C runtime poskytuje funkce class_copyMethodList, class_copyPropertyList, objc_getAssociatedObject. Na rozdíl od Javy Objective-C standardně neskrývá soukromé metody — runtime vidí všechny metody třídy. To vysvětluje, proč method swizzling funguje bez setAccessible: runtime nemá zapouzdření na úrovni metadat.

Použití Reflection v mobilním vývoji

Reflection se používá v klíčových knihovnách mobilního vývoje. Serializace JSON (Gson, Moshi, Kotlinx.serialization) získává vlastnosti objektu přes reflection a přiřazuje je ke klíčům JSON. Dependency injection (Dagger, Koin, Swinject) analyzuje konstruktory a pole pro automatické vkládání závislostí. ORM knihovny (Room, Realm) používají reflection k mapování tříd na tabulky databáze.

  • Serializace — Gson čte deklarovaná pole objektu přes Field.get() a vytváří JSON podle anotací @SerializedName.
  • Dependency Injection — Dagger generuje kód přes annotation processing, Koin používá Kotlin reflection pro řešení závislostí v runtime.
  • Testování — JUnit najde metody s @Test přes reflection a volá je; Mockito vytváří mocky přes dynamic proxy.
  • Databáze — Room kontroluje pole Entity přes Class.getDeclaredFields() ve fázi kompilace (přes KAPT/KSP).
  • Analytika a monitoring — Firebase Crashlytics získává stack trace přes Throwable.getStackTrace(), založený na reflection.

Každé z těchto použití funguje právě v runtime — kód předem neví, s jakými třídami se setká. Reflection poskytuje univerzální mechanismus pro překonání této neznámé za cenu výkonu a bezpečnosti.

Výkon Reflection: cena dynamického přístupu

Reflection je 10–100krát pomalejší než přímé volání metod. Důvod — chybějící optimalizace JIT (devirtualization, inlining), kontrola typů při každém volání a balení parametrů do Object[]/varargs. ART na Androidu 14 nemůže inline-optimalizovat reflection volání, protože cílová metoda je neznámá až do okamžiku provedení.

OperacePřímé voláníPřes ReflectionZpomalení
Volání metody bez parametrů~3 ns~120 ns40x
Čtení pole int~1 ns~85 ns85x
Volání metody se 2 parametry~4 ns~250 ns62x
Vytvoření instance přes konstruktor~5 ns~180 ns36x
Určení třídy podle řetězce~800 ns

Data byla získána na Google Pixel 8 (Android 14, ART). Výkon reflection se s každou verzí Androidu zlepšuje: na Androidu 9 bylo volání přes Method.invoke() 150krát pomalejší než přímé, na Androidu 14 — 40krát. ART používá vestavěné mechanismy method handle pro optimalizaci.

Pro kritické úseky z hlediska výkonu vývojáři nahrazují reflection kódogenerací: Dagger používá annotation processing místo hledání v runtime, Kotlinx.serialization generuje serializátory přes KSP, Moshi přizpůsobuje @JsonClass(generateAdapter = true) pro codegen ve fázi kompilace.

Alternativy k Reflection: anotace a code generation

Annotation processing (KAPT, KSP) a code generation — hlavní alternativy k reflection v mobilním vývoji. Přesouvají analýzu metadat z runtime do compile time: kód se generuje před spuštěním aplikace, což eliminuje režii reflection a zlepšuje výkon.

kotlin
// KSP: code generation místo reflection
@Serializable
data class Config(
    val apiUrl: String,
    val timeout: Int
)

// KSP generuje ConfigSerializer bez reflection
fun loadConfig(json: String): Config {
    return Config.serializer().decodeFromString(json)
}

V tomto příkladu je @Serializable anotace Kotlinx.serialization. KSP (Kotlin Symbol Processing) analyzuje zdrojový kód ve fázi kompilace, najde všechny třídy @Serializable a generuje serializátory. Během provádění aplikace se reflection nepoužívá — serializátor je již zkompilován do strojového kódu.

Porovnání přístupů

Code generation poskytuje lepší výkon, typovou bezpečnost a menší velikost binárního souboru (dead code elimination odstraňuje nepoužívané reflection závislosti). Reflection zůstává nezbytný pro úlohy, kde jsou typy neznámé ve fázi kompilace: dynamické načítání pluginů, runtime-proxy, instrumentace testů. Podle Kotlinu je Kotlinx.serialization s KSP 3–5krát rychlejší než Gson založený na reflection.

Omezení Reflection na Androidu a iOS

Reflection na mobilních platformách má bezpečnostní a výkonnostní omezení. Android od API 28 (Pie) omezuje setAccessible pro non-SDK rozhraní — pokus o otevření skryté systémové metody vede k výjimce nebo varování. iOS se Swiftem nepodporuje reflection v klasickém smyslu: Swift Mirror API poskytuje pouze čtení vlastností (name, value) bez úprav nebo volání metod.

Google Play odmítá aplikace používající reflection k obcházení omezení platformy: náhrada systémových služeb, modifikace politik SELinux, čtení chráněných oprávnění. Apple také blokuje aplikace volající privátní API přes reflection — kontrola App Review skenuje binární soubor na řetězcové signatury objc_msgSend se známými privátními selektory.

ProGuard/R8 — další omezení. Obfuskace a minifikace kódu přejmenovává třídy a metody na krátké názvy (a, b, c). Pokud kód používá Class.forName(„com.example.MyClass”), po obfuskaci se rozbije. Řešení — keep pravidla v proguard-rules.pro:

groovy
// ProGuard keep pravidla pro reflection
-keep class com.example.** { *; }
-keep class * implements java.io.Serializable { *; }
-keepclassmembers class * {
    @com.google.gson.annotations.SerializedName ;
}
-keepattributes Signature, InnerClasses, EnclosingMethod

Pravidla -keep informují R8, aby nepřejmenovával třídy používané přes reflection. Bez těchto pravidel obfuskovaná aplikace spadne s ClassNotFoundException — runtime nenajde třídu podle řetězcového názvu, který se změnil.

Často kladené otázky

Škodí Reflection výkonu aplikace?

Ano, reflection je 10–100krát pomalejší než přímé volání. Hlavní příčiny: chybějící optimalizace JIT (inlining, devirtualization), balení parametrů a kontrola typů při každém volání. Pro produkční kód se doporučuje nahradit reflection code generation přes KSP nebo annotation processing.

Čím se liší Java reflection od Kotlin reflection?

Java reflection funguje přes Class, Method, Field a vyžaduje setAccessible pro private členy. Kotlin reflection používá KClass, KFunction, KProperty a podporuje sealed class, data class, korutiny (suspend funkce) a null-safety. Kotlin reflection je založen na Java reflection, ale přidává type-safe API.

Jak se vyhnout problémům s obfuskací při používání Reflection?

Přidat ProGuard/R8 keep pravidla pro třídy, metody a pole používané přes reflection. Pro každé Class.forName(), getDeclaredMethod(), getDeclaredField() musí existovat odpovídající direktiva -keep. Nástroje jako GreenDAO a Room automaticky generují keep pravidla.

Existuje Reflection ve Swiftu?

Swift nemá reflection v plném smyslu. Mirror API (Swift 2+) umožňuje číst vlastnosti struktury nebo třídy: název, hodnotu, typ. Volání metod, úprava polí a vytváření instancí podle typu nejsou možné. K tomu se používá Objective-C Runtime při dědění z NSObject s @objc dynamic.

Které knihovny používají Reflection na Androidu?

Gson (serializace JSON), Retrofit (vytváření implementací rozhraní přes dynamic proxy), Mockito (vytváření mocků), Koin (dependency injection), Room (kontrola Entity ve fázi kompilace přes KAPT), Firebase Crashlytics (analýza stack trace). Většina knihoven přechází na code generation s KSP/KAPT.

Závěry

  • Reflection — runtime mechanismus pro přístup k metadatům tříd, metod a polí.
  • Java reflection používá Class, Method, Field; Kotlin — KClass, KFunction, KProperty s integrací korutin.
  • Objective-C Runtime poskytuje class_copyMethodList a objc_getClass bez omezení přístupu.
  • Reflection je pomalejší — 10–100krát oproti přímému volání kvůli chybějícím optimalizacím JIT.
  • Alternativy — code generation (KSP, KAPT) a annotation processing — eliminují režii reflection.
  • ProGuard/R8 vyžaduje keep pravidla pro třídy používané přes Class.forName() a getDeclaredMethod().
  • Reflection je nezbytný pro dynamické načítání pluginů, DI a testovacích frameworků, kde jsou typy neznámé ve fázi kompilace.

Vyvineme mobilní aplikaci na klíč

IT Sectr vytváří aplikace pro iOS a Android pro startupy a podniky od roku 2017. Poradíme vám a navrhneme nejlepší řešení.

Prodiskutovat projekt

Přečtěte si také