Reflection sa pag-develop ng app — ano ito, mga mekanismo ng repleksyon at kung paano ilapat

May-akda: IT Sectr Nai-publish: 2026-05-17 Oras ng pagbabasa: 8 min

Reflection (repleksyon) — isang runtime na mekanismo na nagpapahintulot sa code na siyasatin ang sariling istraktura: kumuha ng mga klase, pamamaraan, field at anotasyon nang hindi nalalaman ang mga tipo sa yugto ng kompilasyon. Ang tool na ito ang pundasyon ng maraming mobile framework — JSON serialization (Gson, Moshi), dependency injection (Dagger, Koin) at mga test runner (JUnit, XCTest). Ayon sa Oracle Java Reflection Tutorial, 2024, ang reflection ay isang sapilitang elemento ng platform ng Java na ginagamit ng lahat ng malalaking library.

Mahahalagang punto

  • Reflection — access sa metadata ng mga klase, pamamaraan at field habang tumatakbo ang programa.
  • Java Reflection API ay nagbibigay ng mga klase Class, Method, Field at Constructor para sa dynamic na pagsusuri.
  • Kotlin reflection ay gumagamit ng KClass at KFunction, na isinama sa mga coroutine at serialization.
  • Objective-C Runtime — isang anyo ng reflection sa pamamagitan ng class_copyMethodList at objc_getClass.
  • Ang performance ng reflection ay 10–100 beses na mas mababa kaysa sa direktang tawag dahil sa kawalan ng JIT optimizations.

Ano ang Reflection?

Reflection — ang kakayahan ng programa na obserbahan at baguhin ang sariling istraktura at pag-uugali habang tumatakbo. Sa mga object-oriented na wika, nangangahulugan ito ng pagkuha ng mga bagay na Class, Method, Field at Constructor, na kumakatawan sa mga elemento ng programa bilang data na magagamit para basahin at tawagin.

Ang terminong „reflection” ay ipinakilala sa komunidad ng artificial intelligence noong 1982 (Brian Cantwell Smith) at ipinatupad sa wikang Smalltalk. Sa mobile development, unang lumitaw ang reflection sa Java ME at Objective-C (1986, NextStep). Ngayon bawat malaking mobile platform ay may sariling reflection API: Java/Kotlin para sa Android, Objective-C Runtime para sa iOS, Swift Mirror API para sa Swift.

Ang mekanismo ng reflection ay batay sa metadata na iniimbak ng compiler sa bytecode o binary file. Ang Android ay nag-iimbak ng kumpletong impormasyon tungkol sa mga klase sa mga DEX file, iOS — sa __objc_classlist segment sa Mach-O. Niloload ng Runtime ang metadata na ito sa memory at nagbibigay ng API para sa pagtawid sa mga ito.

Paano gumagana ang Reflection sa Java at Kotlin

Ang Java Reflection API ay binuo sa paligid ng klase na java.lang.Class. Anumang bagay sa Java ay maaaring i-convert sa Class sa pamamagitan ng .getClass() o Class.forName(). Mula sa Class ay kinukuha ang lahat ng pamamaraan, field, constructor, anotasyon at superclass. Ang Kotlin ay nagmamana ng Java reflection at nagdaragdag ng sariling KClass, KFunction, KProperty mula sa package na 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("Property: ${prop.name}, tipo: ${prop.returnType}")
    }
}

Sa halimbawang ito, ang KClass ay nagbibigay ng metadata ng data class User. Ang declaredMemberProperties ay nagbabalik ng listahan ng mga property kasama ang kanilang mga tipo at getter. Ang Kotlin reflection ay malapit na isinama sa mga coroutine: sinusuportahan ng KFunction ang suspend-modifier, na nagpapahintulot sa pagtawag ng mga asynchronous na pamamaraan sa pamamagitan ng reflection.

Java Reflection: Class, Method, Field

Ang Java reflection ay gumagana sa Class<?>, Method.setAccessible() at Field.get(). Ang setAccessible(true) ay nag-o-off sa pagsusuri ng access na Java language access control para sa mga private na elemento. Ito ay isang makapangyarihan ngunit mapanganib na mekanismo: sa Android, mula sa API 28, ang pagtawag ng setAccessible sa mga nakatagong sistema na pamamaraan ay maaaring magdulot ng InaccessibleObjectException.

java
// Java reflection: pagtawag ng pribadong pamamaraan
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");

Ang code ay nagpapakita ng Class.forName() — dynamic na pag-load ng klase batay sa string na pangalan. Ito ang batayan ng mga plugin architecture: ang klase ay maaaring hindi kilala sa yugto ng kompilasyon, ngunit niload at pinatatakbo sa pamamagitan ng reflection sa runtime. Ang getDeclaredMethod(„privateMethod”, ...) ay nakakahanap ng pamamaraan batay sa pangalan at mga tipo ng parameter, at ang invoke ay nagpapatakbo nito.

Objective-C Runtime: alternatibong modelo ng repleksyon

Ang Objective-C runtime ay nagbibigay ng mga function na class_copyMethodList, class_copyPropertyList, objc_getAssociatedObject. Hindi tulad ng Java, ang Objective-C ay hindi nagtatago ng mga private na pamamaraan bilang default — nakikita ng runtime ang lahat ng pamamaraan ng klase. Ipinapaliwanag nito kung bakit gumagana ang method swizzling nang walang setAccessible: ang runtime ay walang encapsulation sa antas ng metadata.

Paglalapat ng Reflection sa mobile development

Ang Reflection ay ginagamit sa mga pangunahing library ng mobile development. Ang JSON serialization (Gson, Moshi, Kotlinx.serialization) ay kumukuha ng mga property ng object sa pamamagitan ng reflection at inilalapat ang mga ito sa mga JSON key. Ang dependency injection (Dagger, Koin, Swinject) ay nagsusuri ng mga constructor at field para sa awtomatikong pag-inject ng mga dependency. Ang mga ORM library (Room, Realm) ay gumagamit ng reflection para sa pagma-map ng mga klase sa mga table ng database.

  • Serialization — binabasa ng Gson ang mga idineklarang field ng object sa pamamagitan ng Field.get() at gumagawa ng JSON batay sa mga @SerializedName anotasyon.
  • Dependency Injection — ang Dagger ay bumubuo ng code sa pamamagitan ng annotation processing, ang Koin ay gumagamit ng Kotlin reflection para sa runtime resolution.
  • Pagsusuri — ang JUnit ay nakakahanap ng mga pamamaraan na may @Test sa pamamagitan ng reflection at tinatawag ang mga ito; ang Mockito ay gumagawa ng mga mock sa pamamagitan ng dynamic proxy.
  • Database — sinusuri ng Room ang mga Entity field sa pamamagitan ng Class.getDeclaredFields() sa yugto ng kompilasyon (sa pamamagitan ng KAPT/KSP).
  • Analytics at monitoring — ang Firebase Crashlytics ay kumukuha ng stack trace sa pamamagitan ng Throwable.getStackTrace(), na batay sa reflection.

Ang bawat isa sa mga paglalapat na ito ay gumagana mismo sa runtime — hindi alam ng code nang maaga kung anong mga klase ang makakaharap nito. Ang Reflection ay nagbibigay ng unibersal na mekanismo para malampasan ang hindi alam na ito kapalit ng performance at seguridad.

Performance ng Reflection: halaga ng dynamic na access

Ang Reflection ay 10–100 beses na mas mabagal kaysa sa direktang pagtawag ng mga pamamaraan. Ang dahilan — kawalan ng JIT optimizations (devirtualization, inlining), pagsusuri ng mga tipo sa bawat tawag at pag-iimpake ng mga parameter sa Object[]/varargs. Ang ART sa Android 14 ay hindi makapag-optimize ng inline ng mga reflection na tawag, dahil ang target na pamamaraan ay hindi kilala hanggang sa sandali ng pagpapatupad.

OperasyonDirektang tawagSa pamamagitan ng ReflectionPagbagal
Pagtawag ng pamamaraan nang walang parameter~3 ns~120 ns40x
Pagbasa ng int field~1 ns~85 ns85x
Pagtawag ng pamamaraan na may 2 parameter~4 ns~250 ns62x
Paglikha ng instance sa pamamagitan ng constructor~5 ns~180 ns36x
Pagtukoy ng klase batay sa string~800 ns

Ang data ay nakuha sa Google Pixel 8 (Android 14, ART). Ang performance ng reflection ay bumubuti sa bawat bersyon ng Android: sa Android 9, ang tawag sa pamamagitan ng Method.invoke() ay 150 beses na mas mabagal kaysa sa direktang, sa Android 14 — 40 beses. Gumagamit ang ART ng built-in na method handle na mekanismo para sa pag-optimize.

Para sa mga bahaging kritikal sa performance, pinapalitan ng mga developer ang reflection ng code generation: ang Dagger ay gumagamit ng annotation processing sa halip na runtime na paghahanap, ang Kotlinx.serialization ay bumubuo ng mga serializer sa pamamagitan ng KSP, ang Moshi ay iniaangkop ang @JsonClass(generateAdapter = true) para sa codegen sa yugto ng kompilasyon.

Mga alternatibo sa Reflection: anotasyon at code generation

Ang annotation processing (KAPT, KSP) at code generation — ang mga pangunahing alternatibo sa reflection sa mobile development. Inililipat nila ang pagsusuri ng metadata mula sa runtime patungo sa compile time: ang code ay binuo bago ilunsad ang app, na nag-aalis ng reflection overhead at nagpapabuti sa performance.

kotlin
// KSP: code generation sa halip na reflection
@Serializable
data class Config(
    val apiUrl: String,
    val timeout: Int
)

// KSP ay bumubuo ng ConfigSerializer nang walang reflection
fun loadConfig(json: String): Config {
    return Config.serializer().decodeFromString(json)
}

Sa halimbawang ito, ang @Serializable ay anotasyon ng Kotlinx.serialization. Ang KSP (Kotlin Symbol Processing) ay nagsusuri ng source code sa yugto ng kompilasyon, nakakahanap ng lahat ng @Serializable na klase at bumubuo ng mga serializer. Sa panahon ng pagpapatakbo ng app, hindi ginagamit ang reflection — ang serializer ay naka-compile na sa machine code.

Paghahambing ng mga diskarte

Ang code generation ay nagbibigay ng mas mahusay na performance, kaligtasan ng mga tipo at mas maliit na binary file (ang dead code elimination ay nag-aalis ng mga hindi ginagamit na reflection dependency). Nananatiling kailangan ang reflection para sa mga gawain kung saan hindi kilala ang mga tipo sa yugto ng kompilasyon: dynamic na pag-load ng mga plugin, runtime proxy, instrumentasyon ng mga test. Ayon sa Kotlin, ang Kotlinx.serialization na may KSP ay 3–5 beses na mas mabilis kaysa sa Gson na batay sa reflection.

Mga limitasyon ng Reflection sa Android at iOS

Ang Reflection sa mga mobile platform ay may mga limitasyon sa seguridad at performance. Ang Android mula sa API 28 (Pie) ay nililimitahan ang setAccessible para sa mga non-SDK na interface — ang pagtatangkang buksan ang nakatagong sistema na pamamaraan ay nagdudulot ng exception o babala. Ang iOS na may Swift ay hindi sumusuporta sa reflection sa klasikal na kahulugan: ang Swift Mirror API ay nagbibigay lamang ng pagbasa ng mga property (name, value) nang walang pagbabago o pagtawag ng mga pamamaraan.

Ang Google Play ay tumatanggi sa mga app na gumagamit ng reflection upang lampasan ang mga limitasyon ng platform: pagpapalit ng mga sistema na serbisyo, pagbabago ng mga SELinux policy, pagbasa ng mga protektadong permiso. Bina-block din ng Apple ang mga app na tumatawag ng mga pribadong API sa pamamagitan ng reflection — ang pagsusuri ng App Review ay nagsi-scan ng binary file para sa mga string signature ng objc_msgSend na may kilalang pribadong selector.

ProGuard/R8 — isa pang limitasyon. Ang obfuscation at minification ng code ay nagpapalit ng pangalan ng mga klase at pamamaraan sa maikling pangalan (a, b, c). Kung ang code ay gumagamit ng Class.forName(„com.example.MyClass”), masisira ito pagkatapos ng obfuscation. Ang solusyon — mga keep na panuntunan sa proguard-rules.pro:

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

Ang mga panuntunang -keep ay nagsasabi sa R8 na huwag palitan ng pangalan ang mga klase na ginagamit sa pamamagitan ng reflection. Kung wala ang mga panuntunang ito, ang na-obfuscate na app ay mag-crash sa ClassNotFoundException — hindi mahahanap ng runtime ang klase batay sa string na pangalan na nabago na.

Mga madalas itanong

Mapanganib ba ang Reflection para sa performance ng app?

Oo, ang reflection ay 10–100 beses na mas mabagal kaysa sa direktang tawag. Ang mga pangunahing dahilan: kawalan ng JIT optimizations (inlining, devirtualization), pag-iimpake ng mga parameter at pagsusuri ng mga tipo sa bawat tawag. Para sa production code, inirerekomenda na palitan ang reflection ng code generation sa pamamagitan ng KSP o annotation processing.

Ano ang pagkakaiba ng Java reflection sa Kotlin reflection?

Ang Java reflection ay gumagana sa pamamagitan ng Class, Method, Field at nangangailangan ng setAccessible para sa mga private na miyembro. Ang Kotlin reflection ay gumagamit ng KClass, KFunction, KProperty at sumusuporta sa sealed class, data class, mga coroutine (suspend function) at null-safety. Ang Kotlin reflection ay batay sa Java reflection, ngunit nagdaragdag ng type-safe na API.

Paano maiiwasan ang mga problema sa obfuscation kapag gumagamit ng Reflection?

Magdagdag ng ProGuard/R8 keep na mga panuntunan para sa mga klase, pamamaraan at field na ginagamit sa pamamagitan ng reflection. Para sa bawat Class.forName(), getDeclaredMethod(), getDeclaredField() ay dapat may kaukulang -keep directive. Ang mga tool tulad ng GreenDAO at Room ay awtomatikong bumubuo ng mga keep na panuntunan.

May Reflection ba sa Swift?

Ang Swift ay walang reflection sa buong kahulugan. Ang Mirror API (Swift 2+) ay nagpapahintulot sa pagbasa ng mga property ng structure o klase: pangalan, halaga, tipo. Ang pagtawag ng mga pamamaraan, pagbabago ng mga field at paglikha ng mga instance batay sa tipo ay hindi posible. Para dito ginagamit ang Objective-C Runtime kapag nagmamana mula sa NSObject na may @objc dynamic.

Anong mga library ang gumagamit ng Reflection sa Android?

Gson (JSON serialization), Retrofit (paglikha ng mga implementation ng interface sa pamamagitan ng dynamic proxy), Mockito (paglikha ng mga mock), Koin (dependency injection), Room (pagsusuri ng Entity sa yugto ng kompilasyon sa pamamagitan ng KAPT), Firebase Crashlytics (pagsusuri ng stack trace). Karamihan sa mga library ay lumilipat sa code generation na may KSP/KAPT.

Mga konklusyon

  • Reflection — runtime na mekanismo para sa pag-access ng metadata ng mga klase, pamamaraan at field.
  • Java reflection ay gumagamit ng Class, Method, Field; Kotlin — KClass, KFunction, KProperty na may integrasyon ng mga coroutine.
  • Objective-C Runtime ay nagbibigay ng class_copyMethodList at objc_getClass nang walang mga limitasyon sa access.
  • Ang reflection ay mas mabagal — 10–100 beses kumpara sa direktang tawag dahil sa kawalan ng JIT optimizations.
  • Mga alternatibo — code generation (KSP, KAPT) at annotation processing — inaalis ang reflection overhead.
  • ProGuard/R8 ay nangangailangan ng mga keep na panuntunan para sa mga klase na ginagamit sa pamamagitan ng Class.forName() at getDeclaredMethod().
  • Ang reflection ay kailangang-kailangan para sa dynamic na pag-load ng mga plugin, DI at mga test framework, kung saan hindi kilala ang mga tipo sa yugto ng kompilasyon.

Gagawa kami ng mobile application na turnkey

Gumagawa ang IT Sectr ng mga iOS at Android application para sa mga startup at negosyo mula noong 2017. Magpapayo kami sa iyo at magmumungkahi ng pinakamahusay na solusyon.

Pag-usapan ang proyekto

Basahin din