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