インスタンスがkotlinかどうかを判定する
インスタンスがkotlinかどうかを判定する方法が知りたかったので調べてみました。
下記バージョンで試してみます。
- kotlin 1.4.21
Model
下記のようなModelをjavaとkotlinで定義します。
JavaModel.java
public class JavaModel { }
KotlinModel.kt
class KotlinModel {
}
Metadataで確認
下記の様に、isKotlinClass()
という拡張関数を定義します。
Class.getDeclaredAnnotation()
でクラスに定義されているアノテーションを取得して、
Metadata
がある場合kotlinクラスになります。
fun Class<*>.isKotlinClass(): Boolean { return this.getDeclaredAnnotation(Metadata::class.java) != null }
確認してみます。
::class.java
でClassクラスのインスタンスを取得して、isKotlinClass()の結果を出力してみます。
fun main() { val kotlinModel = KotlinModel() val javaModel = JavaModel() println("kotlinModel: ${kotlinModel::class.java.isKotlinClass()}") println("javaModel: ${javaModel::class.java.isKotlinClass()}") }
実行すると判定出来ました。
kotlinModel: true javaModel: false
@Metadata
が何かを確認するために、KotlinModel.kt
をdecompileしてみます。
下記のように@Metadata
が付与されています。
kotlinのドキュメントを確認してみると、@Metadata
はkotlinコンパイラによって生成されたクラスに付与されるようです。
https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-metadata/
@Metadata( mv = {1, 4, 1}, bv = {1, 0, 3}, k = 1, d1 = {"\u0000\f\n\u0002\u0018\u0002\n\u0002\u0010\u0000\n\u0002\b\u0002\u0018\u00002\u00020\u0001B\u0005¢\u0006\u0002\u0010\u0002¨\u0006\u0003"}, d2 = {"Lcom/example/kotlin/model/KotlinModel;", "", "()V", "detect-kotlin-class.main"} ) public final class KotlinModel { }
KClass
でも下記のように判定出来るかと思いましたが、
KClass
の場合、kotlin reflection APIで@Metadata
を取得出来ないので無理でした。
fun KClass<*>.isKotlinClass(): Boolean { return this.annotations.any { it.annotationClass == Metadata::class } }
同様に確認してみます。
fun main() { val kotlinModel = KotlinModel() val javaModel = JavaModel() // Can't find from KClass.annotation println("kotlinModel: ${kotlinModel::class.isKotlinClass()}") println("javaModel: ${javaModel::class.isKotlinClass()}") }
下記のように両方falseになってしまいます。
kotlinModel: false javaModel: false
sample codeは下記にあげました。
github.com
おわり。
[参考]
https://github.com/spring-projects/spring-framework/pull/1060/files#diff-244315b45582a5b7573a15644b16c373R48
https://stackoverflow.com/questions/39806721/i-want-to-detect-if-a-jvm-class-is-a-kotlin-class-or-not