Kotlin Android 反射在运行时得到 class
Kotlin Android reflection get class in runtime
我收到服务器的响应,returns 我有不同的对象,每个对象都有一个类型。我如何在运行时将 class 与我从响应中获得的类型相匹配?例如,此代码有效,但我试图摆脱 when 语句并使其更具动态性。
sealed class Tile(
private val id: String,
private val type: String,
private val title: String,
) {
class RedTile(
id: String,
type: String,
title: String,
val stuff: String
) : Tile(id, type, title) {
companion object {
const val TYPE = "RedTile"
}
}
class BlueTile(
id: String,
type: String,
title: String,
val value: Int
) : Tile(id, type, title) {
companion object {
const val TYPE = "BlueTile"
}
}
companion object {
fun parseArray(jsonArrayString: String): List<Tile> {
return JsonParser.parseString(jsonArrayString).asJsonArray
.map { tileJsonObject ->
tileJsonObject as JsonObject
val tile = when (tileJsonObject.get("type").asString) {
Red.TYPE -> Red::class.java
Blue.TYPE -> Blue::class.java
else -> Red::class.java
}
Gson().fromJson(tileJsonObject, tile)
}
}
}
}
使用静态 when
并不是那么糟糕,但我建议将其移至单独的 Tile.getTileClassByType()
函数以保持代码整洁。如果您更喜欢动态搜索 类,则可以使用以下内容:
companion object {
private val tileClassesByType = Tile::class.sealedSubclasses
.associateBy { it.simpleName!! }
fun parseArray(jsonArrayString: String): List<Tile> {
...
val tile = getTileClassByType(tileJsonObject.get("type").asString) ?: RedTile::class
Gson().fromJson(tileJsonObject, tile.java)
...
}
fun getTileClassByType(type: String): KClass<out Tile>? = tileClassesByType[type]
}
以下是我的原回答,没有在问题中提供详细信息。不鼓励这样做,因为最好避免按名称动态加载 类。
您可以使用 Java 标准库中的 Class.forName():
val type = tileJsonObject.get("type").asString
Class.forName("com.example.$type")
请注意您在 type
字段中收到的内容。如果此数据不受信任,那么您应该在使用前对其进行验证,这样另一方就无法在您的应用程序中实例化任意 类 的对象。
我收到服务器的响应,returns 我有不同的对象,每个对象都有一个类型。我如何在运行时将 class 与我从响应中获得的类型相匹配?例如,此代码有效,但我试图摆脱 when 语句并使其更具动态性。
sealed class Tile(
private val id: String,
private val type: String,
private val title: String,
) {
class RedTile(
id: String,
type: String,
title: String,
val stuff: String
) : Tile(id, type, title) {
companion object {
const val TYPE = "RedTile"
}
}
class BlueTile(
id: String,
type: String,
title: String,
val value: Int
) : Tile(id, type, title) {
companion object {
const val TYPE = "BlueTile"
}
}
companion object {
fun parseArray(jsonArrayString: String): List<Tile> {
return JsonParser.parseString(jsonArrayString).asJsonArray
.map { tileJsonObject ->
tileJsonObject as JsonObject
val tile = when (tileJsonObject.get("type").asString) {
Red.TYPE -> Red::class.java
Blue.TYPE -> Blue::class.java
else -> Red::class.java
}
Gson().fromJson(tileJsonObject, tile)
}
}
}
}
使用静态 when
并不是那么糟糕,但我建议将其移至单独的 Tile.getTileClassByType()
函数以保持代码整洁。如果您更喜欢动态搜索 类,则可以使用以下内容:
companion object {
private val tileClassesByType = Tile::class.sealedSubclasses
.associateBy { it.simpleName!! }
fun parseArray(jsonArrayString: String): List<Tile> {
...
val tile = getTileClassByType(tileJsonObject.get("type").asString) ?: RedTile::class
Gson().fromJson(tileJsonObject, tile.java)
...
}
fun getTileClassByType(type: String): KClass<out Tile>? = tileClassesByType[type]
}
以下是我的原回答,没有在问题中提供详细信息。不鼓励这样做,因为最好避免按名称动态加载 类。
您可以使用 Java 标准库中的 Class.forName():
val type = tileJsonObject.get("type").asString
Class.forName("com.example.$type")
请注意您在 type
字段中收到的内容。如果此数据不受信任,那么您应该在使用前对其进行验证,这样另一方就无法在您的应用程序中实例化任意 类 的对象。