【问题标题】:How to serialize/unserialize an Array of Custom object in Kotlin?如何在 Kotlin 中序列化/反序列化自定义对象数组?
【发布时间】:2016-04-20 00:37:56
【问题描述】:

在我的 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 Array 没有扩展 Serializable 并且不开放继承。是否可以通过某种扩展方法“添加”它?

【问题讨论】:

  • 数组序列化在 Kotlin 中也是可以序列化的。这个 sn-p 显示它:gist.github.com/h0tk3y/bc892327ab239121e76df645d32d9832。我不知道为什么引用没有说明它,可能是因为Array&lt;SomeType&gt;被编译成Java的SomeType[],它肯定是可序列化的。

标签: arrays serialization kotlin


【解决方案1】:

事实上,强制转换不是未经检查的,编译器的警告是误导性的。

这是因为在 Kotlin 中,数组由泛型类 Array&lt;T&gt; 表示,编译器将其视为通常的泛型类,并在运行时删除类型参数。

但是在 JVM arrays have reified types 上,当你转换 something as Array&lt;SomeType&gt; 时,生成的字节码确实检查类型参数是 SomeType 以及 somethingArray&lt;*&gt;,这只会发生在任何其他泛型类。

这个例子表明数组转换被检查:

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"),因为实际上不应该有任何警告。

我提交了issue,描述了 Kotlin 问题跟踪器中的问题。

【讨论】:

  • 好的。抱歉重复了,我创建讨论时没有使用您的链接。
  • 也许是一个简单的问题,但是在我的示例中,您会将注释准确地放在哪里(我尝试将 Serializable 检索到文件夹数组中):我没有设法抑制警告。我试过foldersItems = @Suppress("UNCHECKED_CAST") arguments.getSerializable("folders") as Array
  • @loloof64 这应该可以工作:foldersItems = @Suppress("UNCHECKED_CAST") (arguments.getSerializable("folders") as Array&lt;FileItem&gt;)。或者只是注释封闭函数。
【解决方案2】:

这里的强制转换是未检查的,因为这里的编译器不能保证数组的泛型类型参数的可空性

考虑以下示例:

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-12-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多