Kotlin类内val字段调用Color.parseColor赋值后求值结果为0异常
问题原因分析
最高概率原因:类初始化顺序异常,属性未完成初始化就被访问
Kotlin 类的初始化顺序严格遵循如下逻辑:
- 执行父类的主构造函数/init块/次级构造函数
- 按声明顺序执行子类的成员属性初始化
- 执行子类的构造函数体
如果父类的构造逻辑中调用了被子类重写的open方法,且该方法访问了子类的成员属性,此时子类的属性还未完成初始化,会直接返回对应类型的默认值,Int 类型的默认值就是0,完全匹配你遇到的现象。
复现代码示例
open class BaseView { constructor(context: Context) { // 父类构造中调用open方法 initView() } open fun initView() {} } class CoffeeView(context: Context): BaseView(context) { // 子类属性初始化晚于父类构造执行 private val COLOR_COFFEE = Color.parseColor("#6F4E37") override fun initView() { // 此时访问COLOR_COFFEE会得到默认值0 Log.d("init", COLOR_COFFEE.toString()) } fun test(){ // 类初始化完成后访问,属性已赋值,结果正常 Log.d("test", "${COLOR_COFFEE} ${Color.parseColor("#6F4E37")}") } }
其他可能原因
- 你使用了反射直接访问该属性的幕后字段,此时如果属性还未完成赋值(比如使用
by lazy初始化还未触发),会返回默认值0 - 项目接入了存在bug的字节码修改插件、Kotlin编译器插件,篡改了属性的初始化逻辑
解决方案
- 优先排查父类构造逻辑中是否调用了子类重写的方法,禁止在父类构造函数中调用open方法
- 如果必须在初始化早期访问该属性,可以将属性改为
by lazy初始化,访问时会主动触发赋值逻辑:
private val COLOR_COFFEE by lazy { Color.parseColor("#6F4E37") }
- 如果是自定义View相关场景,可以将颜色值放到
res/values/colors.xml中,通过Context加载颜色,避免硬编码解析。
内容的提问来源于stack exchange,提问作者mickstar
相关产品推荐
相关产品推荐

