ProgrammierungBackend-Entwickler

Was sind Inline-Klassen (Value-Klassen) in Kotlin, wofür werden sie verwendet und welche Einschränkungen gibt es bei ihrer Anwendung?

Bestehen Sie Vorstellungsgespräche mit dem Hintsage-KI-Assistenten

Antwort.

Geschichte der Frage

In Kotlin wurde das Konzept der Inline-/Value-Klassen (jetzt Value-Klasse genannt) eingeführt, um den Runtime-Overhead bei der Arbeit mit Wrappers für Primitive und kleinen Strukturen zu minimieren. Die Idee stammt aus anderen Sprachen (zum Beispiel C#-Strukturen), wo eine solche Optimierung nützlich ist, um die Leistung zu steigern, ohne die Typisierung zu verlieren.

Problem

Die Erstellung von Wrapper-Klassen (zum Beispiel für Entity-Typen oder Identifikatoren) ohne Optimierung führt zur Schaffung eines zusätzlichen Objekts im Speicher, was die Leistung, GC beeinflusst und zu Boxing/Unboxing-Overhead führen kann. Oft besteht der Wunsch, eine strenge Typisierung (zum Beispiel UserId anstelle von Int) zu haben, aber ohne tatsächlich Objekte zu erstellen.

Lösung

Die Value-Klasse wird mit dem Modifikator value deklariert. In den meisten Situationen erstellt die JVM kein zusätzliches Objekt — die Value-Klasse wird direkt durch ihr Feld ersetzt (Inlining). Dies bietet Typensicherheit und Leistung, die der von „einfachen Int“ nahekommt.

Beispielcode:

@JvmInline value class UserId(val value: Int) fun showId(id: UserId) = println(id.value) val id = UserId(15) showId(id) // Ohne Erstellung eines separaten Objekts UserId

Wichtige Merkmale:

  • Die Klasse muss genau eine Eigenschaft (val oder var) enthalten, dieser Typ kann jedoch nicht nullable sein.
  • Keine Unterstützung für Vererbung (Value-Klassen können nicht vererbt werden oder von anderen erben).
  • Einige Einschränkungen: init-Block ist nicht möglich, keine late-initialisierten oder nicht initialisierten Eigenschaften, keine Verwendung von Reflexion in allen Fällen.

Fangfragen.

Können Value-Klassen mehrere Eigenschaften haben?

Nein, Value-Klassen können nur eine Eigenschaft enthalten.

// Fehler: // value class Money(val amount: Int, val currency: String)

Kann eine Value-Klasse mit nullable-Eigenschaft erstellt werden?

Das Value-Feld einer Value-Klasse kann nicht nullable sein – nur nicht-nullable Typen.

// Fehler: // value class Name(val value: String?)

Kann Vererbung mit Value-Klassen verwendet werden?

Value-Klassen unterstützen keine Vererbung und können nicht abstrakt oder sealed sein.

// Fehler: // value class NewId(val value: Int): BaseId()

Typische Fehler und Anti-Patterns

  • Versuch, Value-Klassen für komplexe Strukturen (zum Beispiel mit mehreren Feldern) zu verwenden.
  • Speicherung von nullable-Werten über Value-Klassen.
  • Verwendung von Referenzmethoden (zum Beispiel können die Methoden equals/hashCode unerwartet im kompilierten Backend Verhalten).

Beispiel aus der Praxis

Negativer Fall

Ein Entwickler hat eine Value-Klasse für eine Entität mit zwei Eigenschaften (zum Beispiel ein Paar Int und String) erstellt und erhielt einen Kompilierungsfehler.

Vorteile:

  • Versucht, einen strengen Typ zu erreichen. Nachteile:
  • Funktioniert nicht, Kompilierung ist nicht möglich.

Positiver Fall

Ein Entwickler verwendet eine Value-Klasse für einen Identifikator-Typ mit einem Feld (zum Beispiel UserId), was schnell und sicher funktioniert.

Vorteile:

  • Knackiger und sicherer Code.
  • Kein Runtime-Overhead. Nachteile:
  • Kann nur mit einem nicht-nullable Typ verwendet werden.