You need to enable JavaScript to run this app. Kotlin自定义getter访问时触发NullPointerException的原因是什么?
优惠活动
大模型
产品
解决方案
定价
更多

Kotlin自定义getter访问时触发NullPointerException的原因是什么?

问题根因
  • 核心原因1:nameInitials是类内部声明的属性,没有放在主构造参数中,如果你使用@Parcelize实现Parcelable序列化、或者用Gson/Jackson等JSON解析库反序列化实例时,该属性的初始值""不会被正常赋值,会被直接设置为null。
  • 核心原因2:虽然你调用了isNullOrBlank()可空扩展方法,但在部分场景下(比如低版本Kotlin编译器、DataBinding生成的Java代码跨语言调用、API30以上设备误调用Java自带的String.isBlank()成员方法),null调用该方法会触发非空检查抛出空指针。
  • 附加问题:你的nameInitials所有逻辑分支最终都会返回非空字符串,不需要声明为可空类型String?,不必要的可空声明也增加了空指针风险。
修复方案

推荐使用by lazy重写该属性,完全规避空指针问题,同时只做一次计算性能更优:

@Parcelize
data class ModelChatEntry(
    val id: String,
    val name: String?
): BaseModel, Parcelable {

    // 忽略序列化,反序列化后首次访问自动重新计算
    @IgnoredOnParcel
    val nameInitials: String by lazy {
        name?.takeIf { it.isNotBlank() }?.let { nameStr ->
            val splits = nameStr.split(" ")
            when {
                splits.size >= 2 -> "${splits[0].first()} ${splits[1].first()}"
                nameStr.isNotEmpty() -> nameStr.first().toString()
                else -> "-"
            }
        } ?: "-"
    }
}

如果需要保留原有自定义getter写法,可以修改为显式判空:

var nameInitials: String = ""
    get() {
        // 先显式判断null,避免isNullOrBlank的兼容问题
        if (field.isBlank() || field == null) {
            field = name?.takeIf { it.isNotBlank() }?.let { nameStr->
                val splits = nameStr.split(" ")
                when {
                    splits.size > 1 -> "${splits[0].first()} ${splits[1].first()}"
                    nameStr.isNotEmpty() -> nameStr.first().toString()
                    else -> "-"
                }
            }?:"-"
        }
        return field
    }

布局文件不需要做任何修改,即可正常绑定使用。

内容的提问来源于stack exchange,提问作者Naresh NK

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.10 03:36:04