Kotlin类属性值无法显示,打印出现@十六进制串问题求助
Kotlin对象打印显示@十六进制及类型判断问题解决
问题描述
定义Kotlin继承类并赋值后,打印对象时输出@后跟十六进制字符串,无法查看属性值;同时尝试通过character.type区分子类Jedi和Sith时,代码无法识别该变量。相关代码及输出如下:
原代码
open class Character(val name: String) class Jedi(name: String, val age: Int) : Character(name) class Sith(name: String, val hasMask: Boolean) : Character(name) fun characterBuilder(input: String): Character { val (name, type, other) = input.split("-") return when (type) { "jedi" -> Jedi(name, other.toInt()) "sith" -> Sith(name, other.toBoolean()) else -> throw IllegalArgumentException("Unknown character type: $type") } } fun main() { val list = "luke-jedi-25 leia-jedi-25 darkvader-sith-true darksidiuos-sith-false".split(" ") val characters = list.map { characterBuilder(it) } // 代码无法识别该变量 //val (jedis, siths) = characters.partition { character -> character.type == "jedi" } for (character in characters) { println(character) } // println("jedis: ${jedis.size}, siths: ${siths.size}") }
程序输出
Jedi@728938a9 Jedi@21b8d17c Sith@6433a2 Sith@5910e440
问题1:打印对象输出@十六进制字符串的原因及解决方法
原因
Kotlin所有类默认继承自Any类,Any的toString()方法默认输出格式为类名@对象哈希码的十六进制值,因此直接打印对象只会显示这类字符串,无法展示属性内容。
解决方法
有两种常用实现方式:
- 手动重写
toString()方法:在父类或子类中自定义输出格式,示例如下:
open class Character(val name: String) { override fun toString(): String { return "Character(name='$name')" } } class Jedi(name: String, val age: Int) : Character(name) { override fun toString(): String { return "Jedi(name='$name', age=$age)" } } class Sith(name: String, val hasMask: Boolean) : Character(name) { override fun toString(): String { return "Sith(name='$name', hasMask=$hasMask)" } }
- 使用
data class:Kotlin的data class会自动生成包含所有属性的toString()、equals()等方法,只需修改类定义即可:
open data class Character(val name: String) data class Jedi(name: String, val age: Int) : Character(name) data class Sith(name: String, val hasMask: Boolean) : Character(name)
修改后打印对象,即可看到包含属性值的输出,例如Jedi(name='luke', age=25)。
问题2:无法通过character.type区分Jedi和Sith的解决方法
原因
Character类及其子类Jedi、Sith均未定义type属性,因此调用character.type会报错。
解决方法
推荐两种方案:
- 使用
is关键字做类型判断:直接判断对象的实际类型,这是Kotlin类型判断的常规方式,修改partition代码如下:
val (jedis, siths) = characters.partition { it is Jedi }
此时jedis会包含所有Jedi类型对象,siths包含Sith类型对象,后续可通过as关键字强转调用子类属性。
- 在父类中添加
type属性:在Character类中新增type属性,子类构造时传入对应值,即可直接通过type属性判断:
open class Character(val name: String, val type: String) class Jedi(name: String, val age: Int) : Character(name, "jedi") class Sith(name: String, val hasMask: Boolean) : Character(name, "sith") // 同步修改characterBuilder函数,传入type参数 fun characterBuilder(input: String): Character { val (name, type, other) = input.split("-") return when (type) { "jedi" -> Jedi(name, other.toInt()) "sith" -> Sith(name, other.toBoolean()) else -> throw IllegalArgumentException("Unknown character type: $type") } } // 此时partition代码可正常使用 val (jedis, siths) = characters.partition { it.type == "jedi" }
内容的提问来源于stack exchange,提问作者Charles Perry
相关产品推荐
相关产品推荐

