Richard Happe
04/09/2021, 7:38 PMsealed class SealedTypes {
companion object {
val types = setOf(One, Two, Three)
}
object One : SealedTypes()
object Two : SealedTypes()
object Three : SealedTypes()
}
class TypeContainer {
// Whichever type of SealedType this is set to is removed from the types set.
var theType: SealedTypes = One
}
And a test that doesn't really do much:
@RunWith(AndroidJUnit4::class)
class ExampleInstrumentedTest {
@Test
fun test() {
// uncomment this and the test will not crash
// SealedTypes.types
TypeContainer()
SealedTypes.types.forEach { acceptNonNull(it) }
}
fun acceptNonNull(value: SealedTypes) {
// no-op
}
}
test()
surprisingly crashes with a NullPointerException:
java.lang.NullPointerException: Parameter specified as non-null is null: method kotlin.jvm.internal.Intrinsics.checkNotNullParameter, parameter value
at com.personal.ktbugtest.ExampleInstrumentedTest.acceptNonNull(Unknown Source:2)
at com.personal.ktbugtest.ExampleInstrumentedTest.test(ExampleInstrumentedTest.kt:20)
at java.lang.reflect.Method.invoke(Native Method)
...
ephemient
04/09/2021, 7:42 PMephemient
04/09/2021, 7:42 PMval types by lazy { setOf(One, Two, Three) }
it won't crashephemient
04/09/2021, 7:51 PMTypeContainer
loads One
loads SealedTypes
which wants to load One
, Two
, Three
, but doesn't load One
because it is already in the process of being loaded, so One.INSTANCE
is still null when types
is initializedRichard Happe
04/09/2021, 7:52 PMtypes
is being initialized before One
is initialized, and therefore we get a null
reference. Seems unique to the fact that it's a circular reference then.ephemient
04/09/2021, 7:54 PMOne.INSTANCE != null
when constructing the setephemient
04/09/2021, 7:56 PM