-1

i have strange problem in android and kotlin. the problem is i define variable with ArrayList<Long> type but in runtime change to ArrayList<Double>

i define my variable like this:

private var mDivideEntityValue: ArrayList<Long> = arrayListOf()

and use Gson library to assign value like:

// mDivideEntity is string variable store in json array like: ["150","30"]
mDivideEntityValue = Gson().fromJson(mDivideEntity.amounts, ArrayList<Long>()::class.java)

after assign ArrayList<Long> change to ArrayList<Double>

is this kotlin bug? or i miss something?

i use kotlin 1.3.71 and jvm 1.8.

update 0:

kotlin debug arraylist init with ArrayList<Long>

kotlin debug Arraylist init with gson ArrayList<Long>()::class.java

Assing section

Death Programmer
  • 896
  • 2
  • 11
  • 28
  • What makes you say that it "change to ArrayList"? Could you add some code that shows it doing this? Please see [How to create a Minimal, **Reproducible** Example](https://stackoverflow.com/help/minimal-reproducible-example). – Ryan M Mar 31 '20 at 19:29
  • @RyanM i update question. i define `ArrayList` as `Long`. but in next line change type to double in runtime. i say i define var type and must remain and draw exception if other type assign why i get nothing? – Death Programmer Mar 31 '20 at 19:55

1 Answers1

2

Json doesn't have different number types, so by default, all numbers get parsed to a Double. When you pass ArrayList<Long> to fromJson(), Gson cannot see the <Long> type due to type erasure. When you are passing a class type to a Java library, you might as well use <*> as the type.

Kotlin lets the returned ArrayList<Double> get assigned to your ArrayList<Long> property because at runtime it can't tell the difference (type erasure).

However, Arrays do have reified types. This might work (didn't test it):

val divideEntityValue = Gson().fromJson(mDivideEntity.amounts, LongArray::class.java)

That will give you a LongArray rather than ArrayList. Alternatively, you should be able to map the returned list to a List:

mDivideEntityValue = Gson().fromJson(mDivideEntity.amounts, ArrayList::class.java)
    .map { it.toLong() }
Tenfour04
  • 83,111
  • 11
  • 94
  • 154
  • i update question. as i said in question i define `ArrayList` as Long and change type in to `ArrayList` in next line. i think kotlin variable have static type and in this case must draw exception. am i wrong? – Death Programmer Mar 31 '20 at 20:00
  • 1
    Your statement is incorrect. Due to type erasure, an ArrayList has no type at runtime. Kotlin can only warn you at compile time if types don't match. At runtime, it cannot. Since Gson uses reflection to create and populate the list, it does not get checked at compile time. Read up on JVM type erasure for the explanation. – Tenfour04 Mar 31 '20 at 20:13
  • thanks @Tenfour04. can you edit your answer so i can accept it. i read about type erasure at https://www.baeldung.com/java-type-erasure and i understand a little about it. – Death Programmer Mar 31 '20 at 20:29
  • as you said the problem is JVM type erasure in my case. may copy paste comment in answer. – Death Programmer Mar 31 '20 at 20:32
  • 1
    I mentioned it in the second paragraph. – Tenfour04 Mar 31 '20 at 20:40
  • Also see https://stackoverflow.com/questions/33381384/how-to-use-typetoken-generics-with-gson-in-kotlin for a third option. – Alexey Romanov Mar 31 '20 at 21:00