I have a class:
data class Day(val date: String, val events: List<Event>){
val localDateTimeDate: LocalDate by lazy {
LocalDate.parse(date)
}
}
This gets filled from a JSON string (eg. {"date": "2019-06-26", "events": []}
.
If I read someDay.date
, I get "2019-06-26", so the filling part works.
If I read someDay.localDateTimeDate
, I get a nullpointer exception, and I don't see why.
Now, if I go in REPL and fill a "Day" by hand (ie. val day = Day("2019-06-26"", emptyList())
this works.
If I make my android phone do LocalDate.parse("2019-06-26")
, that works.
Day gets filled by:
fun receiveDays(): List<Day> {
val listType = object : TypeToken<List<Day>>() { }.type
val jsonData = (client.readFromSocket()!!.message).toString(Charsets.UTF_8)
val daysList =(Gson().fromJson<List<Day>>(jsonData, listType))
client.sendOK()
return daysList
If I try to read someDay.localDateTimeDate
, I get a nullpointer exception:
2019-08-13 00:06:13.075 21870-21942/nl.joozd.joozdter W/System.err: java.lang.NullPointerException: Attempt to invoke interface method 'java.lang.Object kotlin.Lazy.getValue()' on a null object reference
2019-08-13 00:06:13.075 21870-21942/nl.joozd.joozdter W/System.err: at nl.joozd.joozdter.data.Day.getLocalDateTimeDate(Unknown Source:25)
2019-08-13 00:06:13.075 21870-21942/nl.joozd.joozdter W/System.err: at nl.joozd.joozdter.ui.PdfParserActivity$onCreate$$inlined$let$lambda$1.invoke(PdfParserActivity.kt:140)
2019-08-13 00:06:13.075 21870-21942/nl.joozd.joozdter W/System.err: at nl.joozd.joozdter.ui.PdfParserActivity$onCreate$$inlined$let$lambda$1.invoke(PdfParserActivity.kt:28)
2019-08-13 00:06:13.075 21870-21942/nl.joozd.joozdter W/System.err: at org.jetbrains.anko.AsyncKt$doAsync$1.invoke(Async.kt:143)
2019-08-13 00:06:13.075 21870-21942/nl.joozd.joozdter W/System.err: at org.jetbrains.anko.AsyncKt$doAsync$1.invoke(Unknown Source:0)
2019-08-13 00:06:13.075 21870-21942/nl.joozd.joozdter W/System.err: at org.jetbrains.anko.AsyncKt$sam$java_util_concurrent_Callable$0.call(Unknown Source:2)
2019-08-13 00:06:13.075 21870-21942/nl.joozd.joozdter W/System.err: at java.util.concurrent.FutureTask.run(FutureTask.java:266)
2019-08-13 00:06:13.075 21870-21942/nl.joozd.joozdter W/System.err: at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:301)
2019-08-13 00:06:13.075 21870-21942/nl.joozd.joozdter W/System.err: at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
2019-08-13 00:06:13.075 21870-21942/nl.joozd.joozdter W/System.err: at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
2019-08-13 00:06:13.075 21870-21942/nl.joozd.joozdter W/System.err: at java.lang.Thread.run(Thread.java:764)
If a class doesn't have parameterless constructor, Gson creates an object without calling the constructor, thus the field that stores lazy
delegate doesn't get initialized and you get a NullPointerException when accessing the property delegated to it.
See also this question for the possible solutions: Why Kotlin data classes can have nulls in non-nullable fields with Gson?