如何在Kotlin中序列化/反序列化Custom对象数组?

时间:2016-04-18 07:27:49

标签: arrays serialization kotlin

在我的Kotlin Android项目中,我创建了一个扩展Serializable

的FileItem类
class FileItem(<parameters>) : Serializable, Comparable<FileItem> {

所以我需要将此类的实例序列化为Bundle

val arguments:Bundle = Bundle()
arguments.putSerializable("folders", folders as Serializable)

其中文件夹已声明为:

folders:Array<FileItem> (method parameter)

上面的序列化代码编译时没有任何警告。同时,当我需要反序列化文件夹项时出现问题:

val arguments: Bundle? = getArguments()
if (arguments != null){
    foldersItems = arguments.getSerializable("folders") as Array<FileItem>

其中foldersItems被声明为

var foldersItems: Array<FileItem>?

我收到以下警告,我无法解决没有suppress_warning注释

w: <Path to my class>: (78, 28): Unchecked cast: java.io.Serializable! to kotlin.Array<com.loloof64.android.chess_positions_archiver.main_file_explorer.FileItem>

这种代码在Java / Groovy中编译时没有警告(folderItems则是FileItem []),那么如何修改kotlin代码以使编译器“满意”?

我注意到in official Kotlin documentation Kotlin数组没有扩展Serializable并且不能继承。是否有可能通过一种扩展方法“添加”它?

2 个答案:

答案 0 :(得分:5)

事实上,演员表并未取消选中,编译器的警告会产生误导。

这是因为Kotlin数组由泛型类Array<T>表示,并且编译器将其视为通常的泛型类,其类型参数在运行时被擦除。

但是在JVM arrays have reified types上,当你强制转换something as Array<SomeType>时,生成的字节码确实将类型参数检查为SomeType以及somethingArray<*>只会发生在任何其他泛型类中。

此示例显示已检查数组强制转换:

val a: Any = Array<Int>(1) { 0 }

val i = a as Array<Int>
val d = a as Array<Double> // gets checked and throws ClassCastException

最简单的解决方案确实是@Suppress("UNCHECKED_CAST"),因为实际上不应该有任何警告。

我在Kotlin问题跟踪器中提交了issue来描述问题。

答案 1 :(得分:1)

此处的强制转换未经检查,因为此处的编译器无法确保数组的泛型类型参数的 nullability

考虑以下示例:

fun castAsArrayOfString(param: Any) = param as Array<String>

castAsArrayOfString(arrayOf("a")) // is Array<String>, all ok

castAsArrayOfString(arrayOf("a", null)) // is Array<String>, but contains null

因此,编译器会警告您此演员可能引入的潜在类型安全问题。