instanz :: class.java vs. instance.javaClass

8

Gegeben Kotlin 1.1. Für instance einer Klasse scheinen instance::class.java und instance.javaClass nahezu gleichwertig zu sein:

%Vor%

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:

%Vor%

Also würde ich argumentieren, dass es besser ist, niemals .javaClass für mehr Konsistenz zu verwenden. Gibt es Argumente dagegen?

    
Marco Eckstein 10.10.2017, 19:48
quelle

1 Antwort

8

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>

  • eingegeben
  • foo::class.java wird als Class<out Foo>

  • eingegeben

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:

%Vor%

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.

    
hotkey 10.10.2017 20:26
quelle

Tags und Links