Kotlin Academy · Lektion

Reflection-basierte Validierung und Zuordnung

Erstellen Sie einen einfachen Validator oder Object Mapper mit annotierungsbasierter Reflection.

Lektion 4 von 413 Schritte

Reflection-basierte Validierung und Zuordnung ist eine kostenlose Kotlin Academy-Lektion auf CoddyKit. Dies ist Lektion 4 von 4. Du kannst die komplette Lektion unten kostenlos lesen – dann übst du sie direkt im Browser mit einem integrierten Code-Editor und einem KI-Tutor rund um die Uhr. Sie ist Teil des Kotlin Academy-Lernpfads, und dein Fortschritt wird über Web und CoddyKit-App synchronisiert. Der Kotlin Academy-Kurs umfasst insgesamt 4 Lektionen.

Welches Problem dieses Muster löst

Validierung auf Basis von Reflection liest zur Laufzeit Annotationen aus den Properties einer Klasse aus und wendet Validierungsregeln automatisch an – ohne manuelle Prüfungen für jedes Feld. Dieselbe Technik wird von ORM-Mappern verwendet, die zwischen Objekten und Datenbankzeilen umwandeln.

Die Annotation Validate

Definieren Sie eine Annotation, die zur Laufzeit erhalten bleibt und auf Properties angewendet werden kann:

@Retention(AnnotationRetention.RUNTIME)
@Target(AnnotationTarget.PROPERTY)
annotation class Validate(
    val minLength: Int = 0,
    val maxLength: Int = Int.MAX_VALUE,
    val pattern: String = ""
)

Eine Datenklasse annotieren

Wenden Sie @Validate auf die Properties der Datenklasse an. Der Validator untersucht diese zur Laufzeit:

data class UserForm(
    @Validate(minLength = 2, maxLength = 50) val name: String,
    @Validate(pattern = "^[\\w.]+@[\\w]+\\.[a-z]{2,}$") val email: String,
    @Validate(minLength = 8) val password: String
)

Die Validierungsfunktion

Verwenden Sie KClass.declaredMemberProperties, um über die Properties zu iterieren, Annotationen zu finden und Fehler zu sammeln:

fun validate(obj: Any): List<String> {
    val errors = mutableListOf<String>()
    for (prop in obj::class.declaredMemberProperties) {
        val ann = prop.findAnnotation<Validate>() ?: continue
        val value = (prop as KProperty1<Any, *>).get(obj)?.toString() ?: ""
        if (value.length < ann.minLength) errors += "${prop.name}: too short"
        if (value.length > ann.maxLength) errors += "${prop.name}: too long"
        if (ann.pattern.isNotEmpty() && !value.matches(Regex(ann.pattern)))
            errors += "${prop.name}: invalid format"
    }
    return errors
}

Den Validator ausführen

Rufen Sie validate() mit einem beliebigen annotierten Objekt auf. Die Funktion gibt eine Liste von Fehlermeldungen zurück; eine leere Liste bedeutet, dass das Objekt gültig ist:

val form = UserForm("A", "not-an-email", "short")
val errors = validate(form)
errors.forEach(::println)
// name: too short
// email: invalid format
// password: too short

Objekt-zu-Map-Zuordnung mit @Column

Ein weiteres Reflection-Muster ordnet ein Objekt mithilfe einer @Column-Annotation, die Spaltennamen bereitstellt, einer Map zu:

@Retention(AnnotationRetention.RUNTIME)
@Target(AnnotationTarget.PROPERTY)
annotation class Column(val name: String)

fun toMap(obj: Any): Map<String, Any?> =
    obj::class.declaredMemberProperties
        .mapNotNull { prop ->
            val col = prop.findAnnotation<Column>() ?: return@mapNotNull null
            col.name to (prop as KProperty1<Any, *>).get(obj)
        }.toMap()

Den Mapper verwenden

Annotieren Sie die Datenklasse und rufen Sie toMap() auf, um eine nach Spaltennamen als Schlüssel strukturierte Map zu erhalten, die für eine INSERT-Anweisung bereit ist:

data class User(
    @Column("user_name") val name: String,
    @Column("user_email") val email: String
)

val user = User("Alice", "alice@example.com")
println(toMap(user))
// {user_name=Alice, user_email=alice@example.com}

Reflection-Ergebnisse zwischenspeichern

Reflection-Scans sind aufwendig. Zwischenspeichern Sie die Zuordnung von Properties zu Annotationen beim Start in einer ConcurrentHashMap, deren Schlüssel KClass sind:

val cache = ConcurrentHashMap<KClass<*>, List<Pair<KProperty1<Any,*>, Column>>>()

fun columnsOf(klass: KClass<*>) = cache.getOrPut(klass) {
    klass.declaredMemberProperties
        .mapNotNull { p ->
            p.findAnnotation<Column>()?.let { (p as KProperty1<Any,*>) to it }
        }
}

Validierung und Zuordnung kombinieren

Sie können mehrere Annotationen auf einer einzelnen Property kombinieren und jede unabhängig verarbeiten. Validieren Sie zuerst und führen Sie anschließend die Zuordnung durch – oder erledigen Sie beides in einem Durchlauf, indem Sie jeden Annotationstyp sammeln:

data class Product(
    @Validate(minLength = 1) @Column("product_name") val name: String,
    @Column("price") val price: Double
)

Einschränkungen

Reflection-basierte Validierung ist leistungsfähig, bringt aber Nachteile mit sich: Sie verursacht Laufzeitaufwand, ist auf die Aufbewahrung von Annotationen angewiesen und kann Fehler nicht zur Compile-Zeit erkennen. Für eine performancekritische oder zur Compile-Zeit sichere Validierung sollten Sie stattdessen von KSP generierten Code in Betracht ziehen.

Wann Sie dieses Muster verwenden sollten

Reflection-basierte Validierung eignet sich besonders für Framework-Code, der beliebige benutzerdefinierte Klassen verarbeiten muss: ORMs, Serialisierer, Formularvalidatoren und Konfigurationsbinder. Anwendungscode, der seine Typen selbst kontrolliert, sollte aus Gründen der Geschwindigkeit und Übersichtlichkeit eine explizite Validierung bevorzugen.

Kurzer Test

Welche Retention-Policy für Annotationen ist erforderlich, damit eine Validierungsannotation zur Laufzeit lesbar ist?

Zusammenfassung: Reflection-basierte Validierung und Zuordnung

Die wichtigsten Punkte:

  • Definieren Sie Annotationen, die zur Laufzeit erhalten bleiben und auf Properties angewendet werden können
  • Verwenden Sie declaredMemberProperties und findAnnotation, um die Validierung oder Zuordnung zu steuern
  • Speichern Sie Ergebnisse pro KClass zwischen, um wiederholten Reflection-Aufwand zu vermeiden
  • Kombinieren Sie mehrere Annotationen auf einer Property, um Verhalten zu verbinden
  • Ziehen Sie KSP für Alternativen zur Compile-Zeit in performancekritischen Pfaden in Betracht
Kostenlos starten

Lerne Kotlin mit einem KI-Tutor — kostenlos

Schreibe und führe echten Code in deinem Browser aus, bekomme sofortige Hilfe von einem 24/7 KI-Tutor und setze dein Lernen im Web oder in der App fort.

Kurse
51
Lektionen
203

Häufig gestellte Fragen

Ist die Lektion „Reflection-basierte Validierung und Zuordnung“ kostenlos?

Ja — der vollständige Text von „Reflection-basierte Validierung und Zuordnung“ ist hier im Web kostenlos zu lesen. Um sie interaktiv zu üben (integrierter Code-Editor und 24/7 KI-Tutor) und den Rest des Kotlin Academy-Kurses freizuschalten, upgrade auf CoddyKit PRO. Der Kotlin Academy-Kurs umfasst insgesamt 4 Lektionen.

Was lerne ich in „Reflection-basierte Validierung und Zuordnung“?

Erstellen Sie einen einfachen Validator oder Object Mapper mit annotierungsbasierter Reflection. Du übst Kotlin Academy mit praktischem Code, den du direkt im Browser ausführst, und ein 24/7 KI-Tutor beantwortet deine Fragen während du die Lektion bearbeitest.

Brauche ich Erfahrung, um Kotlin Academy zu starten?

Keine Vorkenntnisse erforderlich. Kotlin Academy auf CoddyKit ist für Anfänger bis fortgeschrittene Lernende strukturiert, sodass du hier starten oder von Anfang an beginnen und in deinem eigenen Tempo voranschreiten kannst. Dies ist Lektion 4 von 4.

Wie lange dauert die Lektion „Reflection-basierte Validierung und Zuordnung“?

Die meisten CoddyKit-Lektionen dauern etwa 5–10 Minuten. Jede ist kompakt und interaktiv, sodass du stetig Fortschritte machst und genau dort weitermachst, wo du aufgehört hast – im Web und in der App.

Kann ich in dieser Kotlin Academy-Lektion Code schreiben und ausführen?

Ja. Jede Kotlin Academy-Lektion enthält einen integrierten Code-Editor, sodass du echten Code direkt in deinem Browser schreibst und ausführst und sofort KI-Feedback erhältst — ohne lokale Einrichtung erforderlich.

Alle Lektionen in diesem Kurs

  1. Kotlin Reflection: KClass, KFunction, KProperty
  2. Benutzerdefinierte Annotationen erstellen und anwenden
  3. Annotationen zur Laufzeit auslesen
  4. Reflection-basierte Validierung und Zuordnung
← Zurück zu Kotlin Academy