class A<E>(val a: E) {
fun <T> get(s: T?) = a as T
fun get(): E = get(null) //Compiles OK, but throw NullPointerException when running.
fun get2(): E = get<E>(null) //Compiles OK and no exceptions.
}
fun main(args: Array<String>) {
val a = A(1)
println(a.get2())
println(a.get())
}
running result is
1
Exception in thread "main" java.lang.NullPointerException
at A.get(Bug.kt:13)
at A.main(Bug.kt:21)
T is different for get() and get2(): Nothing and Int respectively. So that explains why the behavior is different. You can see the inferred type in IntelliJ IDEA if you use this code:
val getBody = a.get(null) // Inferred type is Nothing
val get2Body = a.get<Int>(null) // Inferred type is Int
The fact that the resulting exception of get() is a NullPointerException, seems a bug to me. If I add a function with Nothing as the explicit type to A, I get a ClassCastException when I call it:
fun getNothing(s: Nothing?): Nothing = a as Nothing
Results:
val getBody = a.get(null) // Results in NullPointerException
val getBodyNothing = a.get<Nothing>(null) // Results in NullPointerException
val explicitNothing = a.getNothing(null) // Results in ClassCastException: java.lang.Integer cannot be cast to java.lang.Void
No, it doesn’t. When calling get(T) without a type parameter, the compiler infers the common type of the type of a and the null that you pass to get(T): Nothing.
yeah. val doesn’t help type inference. so the type of a.get(null) is Nothing
If you change the code to val getBody:Int=a.get(null), then the type is Int