前言:将继承Serializable的实体类通过如下方法序列化成字符串,并以SharedPreferences方式保存,当对该实体类添加属性后,再对存储的字符串进行反序列化则会触发java.io.InvalidClassException
/**
* 序列化对象
*/
@Throws(IOException::class)
private fun <A> serialize(obj: A): String {
val byteArrayOutputStream = ByteArrayOutputStream()
val objectOutputStream = ObjectOutputStream(
byteArrayOutputStream)
objectOutputStream.writeObject(obj)
var serStr = byteArrayOutputStream.toString("ISO-8859-1")
serStr = java.net.URLEncoder.encode(serStr, "UTF-8")
objectOutputStream.close()
byteArrayOutputStream.close()
return serStr
}
/**
* 反序列化对象
*/
@Suppress("UNCHECKED_CAST")
@Throws(IOException::class, ClassNotFoundException::class)
private fun <A> deSerialization(str: String): A {
val redStr = java.net.URLDecoder.decode(str, "UTF-8")
val byteArrayInputStream = ByteArrayInputStream(
redStr.toByteArray(charset("ISO-8859-1")))
val objectInputStream = ObjectInputStream(
byteArrayInputStream)
val obj = objectInputStream.readObject() as A
objectInputStream.close()
byteArrayInputStream.close()
return obj
}
原因:如果一个继承Serializable的类未在其中private static final long serialVersionUID ,则它将自动生成,而对该类添加属性后导致自动生成的serivalVersionUID和之前的不一致,而反序列化时如果不一致则触发上述异常
方案:继承Serializable的类定义private static final long serialVersionUID,则不再自动生成,只要该属性不修改,反序列化就不会有上述异常
data class User(
val name: String
val phone: String
): Serializable {
companion object {
@JvmStatic private val serialVersionUID: Long = 1
}
}
而对于java可以通过如下配置File->Settings->Editor->Inspections->Serializable class without 'serialVersionUID'勾选->Ok
将光标放置类名上点击Alt+Enter则会弹出如下
最后:对于kotlin不支持这样便捷生成serialVersionUID的方式,而且对于需要对继承Serializable的类序列化/反序列化如果忘记手动添加了,等到后期添加字段了就导致异常了。可以通过json方式进行序列化和反序列化来规避此问题
/**
* 序列化对象
*/
@Throws(IOException::class)
private fun <A> serialize(obj: A): String {
return Gson().toJson(obj)
}
/**
* 反序列化对象
*/
@Suppress("UNCHECKED_CAST")
@Throws(IOException::class, ClassNotFoundException::class)
private fun <A> deSerialization(str: String, clazz: Class<A>): A {
return Gson().fromJson(str, clazz)
}
?
?
|