Kotlin 1.5.20数据类自动生成的hashCode()方法引发空指针异常问题问询
Yep, I’ve hit this exact problem more than once—it’s a frustrating clash between Gson’s reflection-based instantiation and Kotlin’s non-nullable type guarantees. Let me break down what’s happening and how to fix it:
问题根源
Gson uses Unsafe under the hood to create instances of your Kotlin data class without calling its constructor. This lets it bypass Kotlin’s compile-time non-null checks and directly assign null to fields marked as non-nullable.
Kotlin’s compiler generates hashCode() (along with equals(), toString()) for data classes under the assumption that non-null fields will never be null. So the generated bytecode (like the snippet you shared) calls hashCode() directly on those fields without any null checks—hence the NullPointerException when a field is secretly null.
解决办法
Here are a few practical fixes depending on your constraints:
1. Switch to a Kotlin-first JSON library (best long-term fix)
Libraries like kotlinx.serialization or Moshi are built specifically for Kotlin’s type system. They respect non-nullable rules and won’t instantiate objects with null values for required non-null fields. For example, kotlinx.serialization will throw a clear parsing error if a mandatory non-null field is missing from the JSON, instead of silently setting it to null.
2. Tweak Gson to play nice with Kotlin
If you can’t switch libraries, try these workarounds:
- Add default values to non-null fields: Even if you expect the JSON to provide these values, adding a default lets Gson use the class constructor instead of
Unsafeto initialize the object. Example:data class VoteEvent(val eventId: String = "", val voteId: String = "") - Write a custom TypeAdapter: Create a TypeAdapter for your data class that explicitly checks for null values, throwing an error or providing a fallback to ensure non-null fields are never null.
- Manually override hashCode()/equals(): Add null checks to avoid the NPE. For your example:
Note this defeats the convenience of auto-generated data class methods, but it’ll stop the crash.data class VoteEvent(val eventId: String, val voteId: String) { override fun hashCode(): Int { var result = eventId?.hashCode() ?: 0 result = 31 * result + (voteId?.hashCode() ?: 0) return result } }
3. Enable Gson’s Kotlin support
Make sure you’re using the gson-kotlin artifact (not just core Gson). It adds Kotlin-specific handling for edge cases like default values, though it doesn’t fully fix the Unsafe null issue—you’ll still need the above workarounds for strict non-null fields.
关键提醒
Kotlin’s non-nullable type guarantee is a compile-time check, not a runtime enforcement. Tools like Gson that use reflection/Unsafe can bypass this, leading to unexpected nulls in fields you thought were safe. Always be cautious when mixing such libraries with Kotlin’s strict type system.
内容的提问来源于stack exchange,提问作者xiaobin yáng

