简体   繁体   中英

What's the difference between Foo::class.java and Foo::javaClass?

To initialize my logger apparently I need:

val LOGGER : Logger = LoggerFactory.getLogger(Foo::class.java);

If I do:

val LOGGER : Logger = LoggerFactory.getLogger(Foo::javaClass);

It complains that the parameter type is not compatible with getLogger . However according to the API, both are Class<Foo> . How are they different?

The javaClass is an extension property that returns the runtime Java class of an instantiated object . In your case, it is being used as a property reference, which will give you a KProperty1<Foo, Class<Foo>> representing the extension function itself:

val T.javaClass: java.lang.Class<T>

You could use this in combination with a receiver, eg if Foo provided a default constructor you could say:

Foo::javaClass.get(Foo())

which may be simplified to:

Foo().javaClass

Using ::class.java on the other hand, gives you the Java Class<?> as described in "class references" directly. All three possibilities in a simple example:

val kProperty1: KProperty1<Foo, Class<Foo>> = Foo::javaClass
kProperty1.get(Foo()) //class de.swirtz.kotlin.misc.Foo
Foo::class.java //class de.swirtz.kotlin.misc.Foo
Foo().javaClass //class de.swirtz.kotlin.misc.Foo

javaClass is an extension property which returns the runtime Java class of an object.

/**
 * Returns the runtime Java class of this object.
 */
public inline val <T: Any> T.javaClass : Class<T>
    @Suppress("UsePropertyAccessSyntax")
    get() = (this as java.lang.Object).getClass() as Class<T>

It can be called on an instance of a class, for example:

println(Foo().javaClass)    //class Foo

However, Foo::javaClass give you a property reference of type KProperty1<Foo, Class<Foo>> instead of a Java class instance which can be used to get the class of an instance of Foo through reflection:

val p: KProperty1<Foo, Class<Foo>> = Foo::javaClass
println(p.get(Foo()))    //p.get(Foo()) returns a Java class Foo

Therefore, it is wrong to pass a KProperty to LoggerFactory.getLogger() which accepts a Java class.

Foo::javaClass is a reference to a val defined as

inline val <T : Any> T.javaClass: Class<T>

So you'd have to call it on an instance of Foo like foo.javaClass .

Foo::class gives you the actual KClass of Foo and java is a property of KClass defined as

val <T> KClass<T>.java: Class<T>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM