Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to serialize/unserialize an Array of Custom object in Kotlin?

In my Kotlin Android project, I made a FileItem class which extends Serializable

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

So I needed to Serialize instances of this class into a Bundle

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

where folders has been declared as :

folders:Array<FileItem> (method parameter)

The serialization code above compile without any warning. Meanwhile, the problem comes when I need to unserialize folders items :

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

where foldersItems is declared as

var foldersItems: Array<FileItem>?

I get the following warning, that I can't manage to solve without suppress_warning annotation :

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>

This kind of code compiles in Java/Groovy without warning (folderItems is then a FileItem[]), so how can I modify the kotlin code for the compiler to be "satisfied" ?

I noticed in official Kotlin documentation that Kotlin Array does not extend Serializable and is not open for inheritance. Is it possible meanwhite to "add" it via a kind of extension method ?

like image 935
loloof64 Avatar asked Apr 18 '16 07:04

loloof64


1 Answers

In fact, the cast is not unchecked, the compiler's warning is misleading.

This happens because in Kotlin arrays are represented by generic class Array<T>, and the compiler treats it as usual generic class with type parameters erased at runtime.

But on JVM arrays have reified types, and when you cast something as Array<SomeType>, the generated bytecode really checks the type parameter to be SomeType as well as something being an Array<*>, which would only happen for any other generic class.

This example shows that the array cast is checked:

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

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

The easiest solution is indeed to @Suppress("UNCHECKED_CAST"), because actually there should not be any warning.

I filed an issue describing the problem in Kotlin issue tracker.

like image 72
hotkey Avatar answered Oct 20 '22 22:10

hotkey