Let's say that we have the following:
val person = "Bill"
Could someone explain the difference between these two:
val kClass1 = person.javaClass.kotlin
vs
val kClass2 = person::class
When I should call the one instead of the other?
Any source code example would be appreciated.
The main reason there are two ways to achieve the same thing, namely get the Kotlin class of an object, is because prior to Kotlin 1.1, the ::class
literal did not support the expression on its left-hand side. So if you're using Kotlin 1.0, your only option is .javaClass.kotlin
, otherwise you're fine with either of them. This is the reason "Kotlin in Action" uses the .javaClass.kotlin
syntax: it was written before the Kotlin 1.1 release.
There's also a minor difference in the types of these expressions. For example, in the following code
interface T
fun f1(x: T) = x::class
fun f2(x: T) = x.javaClass.kotlin
f1
's type is KClass<out T>
, but f2
's type is KClass<T>
. This is actually an oversight in the javaClass
declaration: KClass<out T>
is more correct in this case, because x
's class is not necessarily T
, but can also be a subclass of T
.
Otherwise these two expressions (x.javaClass.kotlin
and x::class
) are completely equivalent in terms of produced bytecode and runtime performance. I prefer x::class
because it's shorter and reads better.
person.javaClass.kotlin
creates new Kotlin class reference object from Java class. So it makes sense only if you have only java class object.
So you should use person::class
because in this case you just get Kotlin class directly without additional objects allocation
No one can replace another one, They both have reason to exist.
IF you get a KClass
from a variable that can't be null
then you prefer to using foo::class
since javaClass.kotlin
create a new instance each time, for example:
assert(foo::class === foo::class);
assert(foo.javaClass.kotlin !== foo.javaClass.kotlin);
IF you get a KClass
from a nullable variable then prefer to using as below:
val value:Int? = 1;
val type = value?.javaClass?.kotlin;
IF you get a java Class
from kotlin you want to transform to KClass
then using Class.kotlin
for example:
val javaClass:Class<Integer> = ...;
val kotlinClass:KClass<Integer> = javaClass.kotlin;