https://kotlinlang.org logo
b

bbaldino

07/24/2020, 5:35 PM
I have a method with a generic type
T
bounded by
Any
and call a method which returns a
T
, but in this case
T
is a java type (an enum) and the method (defined in java) returns null. I expected an exception to be thrown here, but instead the value of null trickles up just fine, and a (kotlin) method which is set to return a value
T : Any
ends up happily returning null. Is it expected that this won't throw somewhere? Is this just a limitation of interacting with Java types from kotlin?
I'm trying some simpler cases to reproduce and it seems this isn't inherently the case (TypeCastException gets thrown in my simpler case). I'll have to dig some more to figure out where the safety is getting lost.
s

streetsofboston

07/24/2020, 5:48 PM
Without seeing your code, I think what happens is that your Java method returns that enum as a so-called platform type (E.g
MyEnum!
, with the exclamation mark
!
). Values of this type can be null but can be assigned to non-nullable variables. At some point, when you finally access the platform-type value and expect it to be not null, you’ll get a null-pointer-exception.
b

bbaldino

07/24/2020, 5:51 PM
Yeah, that's exactly what I expected (that, upon access, I'd get the exception) but I didn't...Something weird must be happening somewhere. I'm trying to reproduce with less code.
Alright, I'm seeing some weird things (in my real code, it actually makes a difference of getting 'null' vs an exception if I use a method reference vs a lambda in one place...but I haven't repro'd that in a simple example yet). I did write up this: https://pl.kotl.in/vFsPfaJt7
(I can't simulate a platform type in playground, as far as I know?)
But both bits there print 'null' when I would've thought at least the second one would throw. What 'triggers' treating a platform type as a Kotlin non-nullable type?
s

streetsofboston

07/24/2020, 6:16 PM
I think the Kotlin compiler sprinkles in null-checks (requireNull) into the byte-code only in certain spots, e.g. when providing an argument to a function-parameter. I would expect it to happen on the assignment of a
return
statement as well… (
get(): NewType =
), but I guess it doesn’t….
b

bbaldino

07/24/2020, 6:16 PM
Yeah, I think that's what I had assumed
If, in that snippet, I change
Converter#get
to:
Copy code
fun get(): NewType = converter(originalValue).also {
    if (it == null) {
        println("null!")
    }
}
then kotlin warns me the check is redundant (since it thinks
it
can't be null), but it does print
null!
... 😛
I dunno...I ended up filing https://youtrack.jetbrains.com/issue/KT-40596 because it's odd to me that even explicitly declaring the type as a non-nullable kotlin type (not the inferred platform type) doesn't throw an exception when it's null.
It can actually make a difference if a lambda is used vs. a method reference, looks like.
E.g. this will throw:
Copy code
val a = Converter<String, MyEnum>("blah") { MyEnum.fromString(it) }
    println(a.get())
but this will print `null`:
Copy code
val c = Converter<String, MyEnum>("blah", MyEnum::fromString)
    println(c.get())
5 Views