Perhaps we have a little misunderstanding what my ...
# language-proposals
j
Perhaps we have a little misunderstanding what my proposal is about. I do not propose to create a non-inline overload with
Class<T>
parameter for an inline method that has a reified type parameter, but a non-inline method which is „annotated“ with the modifier
reified
and uses the type
T
as if it were an inline method with reified type parameter. Kotlin will generate this to a method with an implicit
Class<T>
parameter (which is not visible in Kotlin) and iff
T
has no upper bound at all a boolean flag is added which says whether the reified type is an optional/nullable or not (this seems to be a special case for
T
without any bound that I wasn’t aware of. This works because an optional has default implementations for
toString()
and co., so that it works as expected even if a null is passed). The Kotlin compiler will/would add an overload to this function without the implicit parameter (a non-inline function), which can be called from Java. It passes the raw type of the upper bound as
cls
(and true for the nullable flag) parameter. It’s just to have a nice Java API without exposing the implicit
cls
parameter. So in Kotlin it would look like this (not a very meaningful example):
Copy code
fun <reified T> foo(): T? {
  val str = „Hello“
  if (str is T) {
    return str
  }
  else {
    return null
  }
}

fun test() {
  val myStr: String? = foo()
}
So this should print out
Hello
. Let me show the byte code implementation the Kotlin compiler should compile from this, but since IMHO byte code is not so readable I will use semantically equivalent Kotlin code:
Copy code
// for Java
@Suppress("UNCHECKED_CAST")
fun <T> foo(): T? {
    return foo(cls = Any::class.java, nullable = true) as T
}

// the nullable is only necessary iff there is no upper bound
fun <T> foo(cls: Class<T>, nullable: Boolean): T? {
    val str = "Hello"
    // a nullable check is unnecessary, because `str` can never be `null`
    if(cls.isAssignableFrom(str.javaClass)) {
        return cls.cast(str)
    }
    else {
        return null
    }
}

fun main(args: Array<String>) {
    // This is how it is called from "compiled Kotlin".
    val myStr: String? = foo(cls = String::class.java, nullable = false)
    // This is how Java would call it...
    val myStr2: Any? = foo()
    println(myStr)
    println(myStr2)
}
So with my proposal Kotlins compiler can check what you are doing with the reified type, which is not possible if you pass the class object as a default parameter, because then you are doing reflection in Kotlin instead of let Kotlins compiler check and handle this.