0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【Kotlin】KClassがvalue class(inline class)かを判定する(kotlin-reflect無しでもOK)

Last updated at Posted at 2021-05-23

TL;DR

  • Kotlin 1.5以降 -> KClass::isValueで判定できる1
    • ただし、kotlin-reflectが必要
  • Kotlin 1.4以下 or kotlin-reflect無し -> 正式な方法は提供されていない
    • 代替となりうる手段は有る

本文では代替となりうる手段の方を中心に解説します。

代替となりうる手段

以下2つのやり方を紹介します。

  • value class特有の関数の名前から判定する
    • Kotlinのバージョンに関係なく動作しそう
    • エッジケースで誤判定の可能性有り
  • JvmInlineアノテーションを探す
    • 条件をKotlin 1.5以上に限れるなら、エッジケースに気を配らずに書けるためこちらが良さそう
    • Kotlin 1.4以前で実際に動作するかは不明

kotlinx-metadata-jvmを使うことでも判定できますが、外部ライブラリが必要になるためここでは一旦説明しません。

value class特有の関数の名前から判定する

value classは特有の関数名を持つstaticメソッドをコンパイル時に生成します。
代表的な例としては以下が有ります。

  • constructor-impl2
  • box-impl/unbox-impl
  • toString-impl/hashCode-impl

よって、この名前を持つメソッドが含まれるかから判定することができます。

判定関数例
import kotlin.reflect.KClass

fun KClass<*>.myIsValue() = this.java.declaredMethods.any { it.name == "box-impl" }

ただし、エッジケースとして、Kotlin上でbox-implという名前の関数を書くことはできるため、そのような関数が含まれる内容に対してこの判定関数を実行すると誤判定します。
仮に厳密さを求める場合、対処療法的になってしまいますが、以下のような条件を加えることが考えられます。

  • 複数の関数名が全て含まれる
  • 対象関数がstatic
  • Class<*>.declaredFieldsのサイズが1

補足

この判定方式は下記を参考にさせて頂きました。

物凄く細かい話ですが、手元で確認した所、対象関数の内declaredMethodsで取得できるのはbox-implが最初だったので、例ではこれをそのまま使っています。

JvmInlineアノテーションで判定する

以下はKotlin 1.5以上のみで可能な方法です。

Kotlin 1.5以上では、value classには必ずJvmInlineアノテーションを付与する必要が有ります。

定義例
@JvmInline
value class ValueClass(val value: Int)
デコンパイル結果
@JvmInline
@Metadata( /* 省略 */ )
public final class ValueClass {

よって、これを探すことで確認が可能です。

判定関数例
import kotlin.reflect.KClass

fun KClass<*>.myIsValue() = this.java.annotations.any { it is JvmInline }

ただし、このアノテーションは@SinceKotlin("1.5")となっており、それ以前の環境からは普通に参照することができません。
クラス名(kotlin.jvm.JvmInline)から比較を行う方法も有るかもしれませんが、Kotlin 1.4以前の内容が絡む際に動くかは未知数です。

  1. isValue - Kotlin Programming Language

  2. これはstaticメソッドであり、コンストラクタではありません。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?