2017.10.17 Kotlin Initialization Order Gotcha - GlenKPeterson/One-off_Examples GitHub Wiki

I have a simple class whose constructor takes a somewhat unusual parameter:

class InitIssue(reactor: (InitIssue) -> Int) {
    val x: Int = reactor.invoke(this)
    var items : MutableList<String> = mutableListOf()

    fun addStr(s:String):Int {
        println("items: " + items)
        items.add(s)
        return items.size
    }
}

When I call this code like so:

InitIssue{ initIssue:InitIssue -> initIssue.addStr("hi") }

I get

items: null

java.lang.NullPointerException
	at InitIssue.addStr(InitIssue.kt:9)
	at TestManual2$testInitIssue$1.invoke(TestManual2.kt:38)
	at TestManual2$testInitIssue$1.invoke(TestManual2.kt:35)
	at InitIssue.<init>(InitIssue.kt:4)
	at TestManual2.testInitIssue(TestManual2.kt:38)

Switching the declaration order of x and items fixes the issue:

class InitIssue(reactor: (InitIssue) -> Int) {
    var items : MutableList<String> = mutableListOf()
    val x: Int = reactor.invoke(this)

    fun addStr(s:String):Int {
        println("items: " + items)
        items.add(s)
        return items.size
    }
}

Output:

items: []

Why? I think the fields are initialized in order. In the first one, items is not yet initialized when you call reactor.invoke(). In the second, it is. I'm not sure if this can or should be fixed, but it's something to be aware of. In Java, I remembered to use this only at the end of a constructor.

⚠️ **GitHub.com Fallback** ⚠️