Zum Inhalt springen
Anjunar/ DOCS

Generics

Einfache Reflection sagt dir, dass eine Methode T zurückgibt. scala-universe sagt dir, was T für die Klasse ist, nach der du gefragt hast.

Rückgabetypen

Mit konkretem Typ überschrieben

Die Unterklasse überschreibt eine generische Methode. Die aufgelöste Methode ist die der Unterklasse, und ihr Rückgabetyp ist konkret.

scala
abstract class Box[T] { def getValue: T } class StringBox extends Box[String] { override def getValue: String = "hello" } val method = TypeResolver.resolve(classOf[StringBox]).findMethod("getValue") println(method.returnType.raw) // class java.lang.String
Geerbte Member

Generisch deklariert, konkret aufgelöst

Auch ohne Überschreibung geerbte Member werden gegen den Ausgangstyp aufgelöst: Felder, Rückgabetypen und Parameter.

scala
abstract class Repository[E] { var items: java.util.List[E] = new java.util.ArrayList[E]() def save(entity: E): E = entity } class UserRepository extends Repository[User] val repository = TypeResolver.resolve(classOf[UserRepository]) val save = repository.findMethod("save", classOf[Object]) println(save.parameters.head.parameterType.name) // User println(save.returnType.name) // User println(repository.findField("items").fieldType.typeArguments(0)) // ResolvedClass(User)
Über gelöschte Parameter suchen

findMethod vergleicht die JVM-Signatur; ein Parameter vom Typ E wird deshalb als classOf[Object] gefunden. Der aufgelöste parameterType sagt dann User.

Ungebundene Variablen

Beim konkreten Typ beginnen

Wer die generische Klasse selbst auflöst, lässt ihre Typvariablen ungebunden. In 1.0.4 ist die Rohklasse einer ungebundenen Variable die Klasse, die sie deklariert, nicht ihre Schranke.

scala
val generic = TypeResolver.resolve(classOf[Repository[?]]) val save = generic.findMethod("save", classOf[Object]) println(save.returnType.underlying) // E println(save.returnType.raw) // class example.Repository
Über die Unterklasse auflösen

Code, der raw oder name eines Member-Typs liest, sollte bei einer konkreten Klasse wie UserRepository beginnen. Der Start bei Repository[?] liefert eine Typvariable, deren Rohklasse nichts über ihre Werte sagt.

Typargumente

Collections kennen ihre Elemente

typeArguments eines parametrisierten Typs sind selbst ResolvedClasses. Darüber erzeugt json-mapper für jedes JSON-Array den richtigen Elementtyp.

scala
def elementType(property: AbstractProperty): ResolvedClass = property.propertyType.typeArguments.headOption.getOrElse(TypeResolver.resolve(classOf[Object]))