Gegeben Kotlin 1.1. Für instance
einer Klasse scheinen instance::class.java
und instance.javaClass
nahezu gleichwertig zu sein:
Es gibt jedoch einen feinen Unterschied:
%Vor% instance.javaClass
ist vernachlässigbar kürzer, aber instance::class.java
ist konsistenter mit der entsprechenden Verwendung eines Typs. Während Sie .javaClass
für einige Typen verwenden können, ist das Ergebnis möglicherweise nicht das, was Sie erwarten würden:
Also würde ich argumentieren, dass es besser ist, niemals .javaClass
für mehr Konsistenz zu verwenden. Gibt es Argumente dagegen?
Der Unterschied zwischen diesen beiden Konstrukten besteht darin, dass für einen Ausdruck foo
des statischen (deklarierten oder abgeleiteten) Typs Foo
:
foo.javaClass
wird als Class<Foo>
foo::class.java
wird als Class<out Foo>
Tatsächlich ist letzteres genauer, weil der tatsächliche Wert, den foo
auswertet, eine Instanz von nicht Foo
selbst sein kann, aber einer seiner Subtypen (und genau das ist, was durch die Kovariante out Foo
angegeben wird) .
Wie @marstran im Kommentar zu der Frage richtig bemerkt hat, wurde .javaClass
einmal als veraltet angesehen (siehe Kotlin 1.1 RC-Ankündigung ), weil es Typsicherheit (siehe unten) brechen kann, aber es wurde danach wie es ist, weil es weit verbreitet war und es ersetzt Mit der Alternative ::class.java
würde das Hinzufügen expliziter ungeprüfter Umwandlungen im Code erforderlich sein.
Siehe auch die Kommentare unter dieser Antwort: (Link)
Bitte beachten Sie, dass Int.javaClass
nicht den Typ von Int
angibt, sondern stattdessen die Java-Klasse des Begleitobjekts von Int
. Während Int::class.java
eine ungebundene Klassenreferenz ist und den Typ angibt. Um es mit .javaClass
zu erhalten, müssen Sie es in einer Int
-Instanz aufrufen, z. 1.javaClass
.
Genau so kann .javaClass
die Typensicherheit unterbrechen. Dieser Code wird kompiliert, bricht jedoch zur Laufzeit:
In diesem Beispiel wird kotlin-reflect
verwendet.
Das liegt daran, dass someFooProperty
eine Eigenschaft von Bar
, nicht Foo
darstellt, aber da sie von someFoo.javaClass
( Class<Foo>
, dann konvertiert in KClass<Foo>
) erhalten wurde, erlaubt uns der Compiler die Verwendung mit in Foo
Projektion.
Tags und Links reflection kotlin