After deserialisation, none of the @Transient variables will be initialized


#1

When we serialize a data class object and deserialize it again, any variables we set to Transient will be set to null, even though we didn’t explicitly tell Kotlin that it can be null. This will result in a Java nullpointerexception when we try to work with it, which feels counterintuitive to me.

Here an example

data class Test(val constructorVariable: String): Serializable {
    val nonTransientVariable = "Not transient"
    @Transient val transientVariable = "Is transient"
}

val debug: (Test) -> Unit = {
    Log.d("Test", "Object toString: $it")
    Log.d("Test", "Constructor variable: ${it.constructorVariable}")
    Log.d("Test", "Non-transient variable: ${it.nonTransientVariable}")
    Log.d("Test", "Transient variable: ${it.transientVariable}")
}


val objectIn = Test("sdf")
// Output our control object
Log.d("Test", "-----------------------")
Log.d("Test", "Testing original object")
debug.invoke(objectIn)

//serialize object
val byteArrayOutputStream = ByteArrayOutputStream()
val objectOutputStream = ObjectOutputStream(byteArrayOutputStream)
objectOutputStream.writeObject(objectIn)

// Write to bytes
val bytes = byteArrayOutputStream.toByteArray()

// Deserialize object
val objectInputStream = ByteArrayInputStream(bytes).use { ObjectInputStream(it) }
val objectOut = objectInputStream.readObject() as Test

// Output our result
Log.d("Test", "-----------------------")
Log.d("Test", "Testing deserialized object")
debug.invoke(objectOut)

And we get the following result:

D/Test: -----------------------
D/Test: Testing original object
D/Test: Object toString: Test(constructorVariable=sdf)
D/Test: Constructor variable: sdf
D/Test: Non-transient variable: Not transient
D/Test: Transient variable: Is transient
D/Test: -----------------------
D/Test: Testing deserialized object
D/Test: Object toString: Test(constructorVariable=sdf)
D/Test: Constructor variable: sdf
D/Test: Non-transient variable: Not transient
D/Test: Transient variable: null

As you can see, the transient variable has been set to null, this can result in subtle issues and nullpointers where you aren’t expecting it. What would feel natural to me is that variables that were set to Transient to reinitialize with their default value.